Message ID | 20160220105420.GB13147@msticlxl57.ims.intel.com |
---|---|
State | New |
Headers | show |
On Sat, Feb 20, 2016 at 01:54:20PM +0300, Ilya Verbin wrote: > gcc/ > PR driver/68463 > * config/gnu-user.h (GNU_USER_TARGET_STARTFILE_SPEC): Add > crtoffloadbegin.o for -fopenacc/-fopenmp if it exists. > (GNU_USER_TARGET_ENDFILE_SPEC): Add crtoffloadend.o for > -fopenacc/-fopenmp if it exists. > * lto-wrapper.c (offloadbegin, offloadend): Remove static vars. > (offload_objects_file_name): New static var. > (tool_cleanup): Remove offload_objects_file_name file. > (find_offloadbeginend): Replace with ... > (find_crtoffloadtable): ... this. > (run_gcc): Remove offload_argc and offload_argv. > Get offload_objects_file_name from -foffload-objects=... option. > Read names of object files with offload from this file, pass them to > compile_images_for_offload_targets. Don't call find_offloadbeginend and > don't pass offloadbegin and offloadend to the linker. Don't pass > offload non-LTO files to the linker, because now they're not claimed. > libgcc/ > PR driver/68463 > * Makefile.in (crtoffloadtable$(objext)): New rule. > * configure.ac (extra_parts): Add crtoffloadtable$(objext) if > enable_offload_targets is not empty. > * configure: Regenerate. > * offloadstuff.c: Move __OFFLOAD_TABLE__ from crtoffloadend to > crtoffloadtable. > lto-plugin/ > PR driver/68463 > * lto-plugin.c (struct plugin_offload_file): New. > (offload_files): Change type. > (offload_files_last, offload_files_last_obj): New. > (offload_files_last_lto): New. > (free_2): Adjust accordingly. > (all_symbols_read_handler): Don't add offload files to lto_arg_ptr. > Don't call free_1 for offload_files. Write names of object files with > offloading to the temporary file. Add new option to lto_arg_ptr. > (claim_file_handler): Don't claim file if it contains offload sections > without LTO sections. If it contains offload sections, add to the list. LGTM. Jakub
Hi! On Sat, 20 Feb 2016 13:54:20 +0300, Ilya Verbin <iverbin@gmail.com> wrote: > On Fri, Feb 19, 2016 at 15:53:08 +0100, Jakub Jelinek wrote: > > On Wed, Feb 10, 2016 at 08:19:34PM +0300, Ilya Verbin wrote: > > > This patch adds crtoffload{begin,end}.o to all -fopenmp programs, if they exist. > > > I couldn't think of a better solution... > > > Tested using the testcase from the previous mail, e.g.: > > > > > > $ gcc -DNUM=1 -c -fopenmp test.c -o obj1.o > > > $ gcc -DNUM=2 -c -fopenmp test.c -o obj2.o > > > $ gcc -DNUM=3 -c -fopenmp test.c -o obj3.o > > > $ gcc -DNUM=4 -c -fopenmp test.c -o obj4.o -flto > > > $ gcc -DNUM=5 -c -fopenmp test.c -o obj5.o > > > $ gcc -DNUM=6 -c -fopenmp test.c -o obj6.o -flto > > > $ gcc -DNUM=7 -c -fopenmp test.c -o obj7.o > > > $ gcc-ar -cvq libtest.a obj3.o obj4.o obj5.o > > > $ gcc -fopenmp main.c obj1.o obj2.o libtest.a obj6.o obj7.o > > > > > > And other combinations. > Thomas, could you please test it using nvptx It mostly ;-) works. With nvptx offloading enabled (which you don't have, do you?), I'm seeing one test case regress: [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 9) [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 13) PASS: libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for excess errors) [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 execution test (Same for C++.) That testcase, just recently added by Tom in r233237 "Handle -fdiagnostics-color in lto", specifies 'dg-additional-options "-flto -fno-use-linker-plugin"'. Is that now an unsupported combination/configuration? (I have not yet looked in detail, but it appears as if the offloading compilers are no longer being run for -fno-use-linker-plugin.) > including the testcase with static > libraries? Works in my manual testing if I work around the following issue: > --- a/gcc/config/gnu-user.h > +++ b/gcc/config/gnu-user.h > @@ -49,14 +49,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > %{" NO_PIE_SPEC ":crtbegin.o%s}} \ > %{fvtable-verify=none:%s; \ > fvtable-verify=preinit:vtv_start_preinit.o%s; \ > - fvtable-verify=std:vtv_start.o%s}" > + fvtable-verify=std:vtv_start.o%s} \ > + %{fopenacc|fopenmp:%:if-exists(crtoffloadbegin%O%s)}" (..., and similar for others.) The if-exists spec function only works for absolute paths (I have not researched, why?), so it won't locate the files for relative -Bbuild-gcc/[...] prefixes, and linking will fail: /tmp/ccGajPD4.crtoffloadtable.o:(.rodata+0x0): undefined reference to `__offload_func_table' /tmp/ccGajPD4.crtoffloadtable.o:(.rodata+0x8): undefined reference to `__offload_funcs_end' /tmp/ccGajPD4.crtoffloadtable.o:(.rodata+0x10): undefined reference to `__offload_var_table' /tmp/ccGajPD4.crtoffloadtable.o:(.rodata+0x18): undefined reference to `__offload_vars_end' If I use the absolute -B$PWD/build-gcc/[...], it works. (But there is no requirement for -B prefixes to be absolute, as far as I know.) Why not make it a hard error, though, if these files are missing? Can we use something like (untested pseudo-patch): +#ifdef ENABLE_OFFLOADING +# define CRTOFFLOADBEGIN "%{fopenacc|fopenmp:%:crtoffloadbegin%O%s}" +#else +# define CRTOFFLOADBEGIN "" +#endif @@ -49,14 +49,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see %{" NO_PIE_SPEC ":crtbegin.o%s}} \ %{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_start_preinit.o%s; \ - fvtable-verify=std:vtv_start.o%s}" + fvtable-verify=std:vtv_start.o%s} \ + " CRTOFFLOADBEGIN ")}" I have not verified your patch's logic in detail (arcane...) ;-) so just two drive-by comments: > #else > #define GNU_USER_TARGET_STARTFILE_SPEC \ > "%{!shared: %{pg|p|profile:gcrt1.o%s;:crt1.o%s}} \ > crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s} \ > %{fvtable-verify=none:%s; \ > fvtable-verify=preinit:vtv_start_preinit.o%s; \ > - fvtable-verify=std:vtv_start.o%s}" > + fvtable-verify=std:vtv_start.o%s} \ > + %{fopenacc|fopenmp:%:if-exists(crtoffloadbegin%O%s)}" > #endif > #undef STARTFILE_SPEC > #define STARTFILE_SPEC GNU_USER_TARGET_STARTFILE_SPEC > @@ -73,13 +75,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > fvtable-verify=preinit:vtv_end_preinit.o%s; \ > fvtable-verify=std:vtv_end.o%s} \ > %{shared:crtendS.o%s;: %{" PIE_SPEC ":crtendS.o%s} \ > - %{" NO_PIE_SPEC ":crtend.o%s}} crtn.o%s" > + %{" NO_PIE_SPEC ":crtend.o%s}} crtn.o%s \ > + %{fopenacc|fopenmp:%:if-exists(crtoffloadend%O%s)}" > #else > #define GNU_USER_TARGET_ENDFILE_SPEC \ > "%{fvtable-verify=none:%s; \ > fvtable-verify=preinit:vtv_end_preinit.o%s; \ > fvtable-verify=std:vtv_end.o%s} \ > - %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s" > + %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s \ > + %{fopenacc|fopenmp:%:if-exists(crtoffloadend%O%s)}" > #endif > #undef ENDFILE_SPEC > #define ENDFILE_SPEC GNU_USER_TARGET_ENDFILE_SPEC I guess we currently don't have to care about offloading configurations not using the gnu-user.h file in which you modified the STARTFILE_SPEC/ENDFILE_SPEC? > --- a/lto-plugin/lto-plugin.c > +++ b/lto-plugin/lto-plugin.c > @@ -671,16 +681,37 @@ all_symbols_read_handler (void) > + if (num_offload_files > 0) > { > + [...] > + struct plugin_offload_file *ofld; > + [...] > + ofld = offload_files->next; > + while (ofld) > + { > + fprintf (f, "%s\n", ofld->name); > + ofld = ofld->next; > + } To the casual reader, skipping the first offload_files looks like a off-by-one error, so I suggest you add a comment "Skip the dummy item at the start of the list.", or similar. Grüße Thomas
2016-02-22 18:13 GMT+03:00 Thomas Schwinge <thomas@codesourcery.com>: > On Sat, 20 Feb 2016 13:54:20 +0300, Ilya Verbin <iverbin@gmail.com> wrote: >> On Fri, Feb 19, 2016 at 15:53:08 +0100, Jakub Jelinek wrote: >> > On Wed, Feb 10, 2016 at 08:19:34PM +0300, Ilya Verbin wrote: >> > > This patch adds crtoffload{begin,end}.o to all -fopenmp programs, if they exist. >> > > I couldn't think of a better solution... >> > > Tested using the testcase from the previous mail, e.g.: >> > > >> > > $ gcc -DNUM=1 -c -fopenmp test.c -o obj1.o >> > > $ gcc -DNUM=2 -c -fopenmp test.c -o obj2.o >> > > $ gcc -DNUM=3 -c -fopenmp test.c -o obj3.o >> > > $ gcc -DNUM=4 -c -fopenmp test.c -o obj4.o -flto >> > > $ gcc -DNUM=5 -c -fopenmp test.c -o obj5.o >> > > $ gcc -DNUM=6 -c -fopenmp test.c -o obj6.o -flto >> > > $ gcc -DNUM=7 -c -fopenmp test.c -o obj7.o >> > > $ gcc-ar -cvq libtest.a obj3.o obj4.o obj5.o >> > > $ gcc -fopenmp main.c obj1.o obj2.o libtest.a obj6.o obj7.o >> > > >> > > And other combinations. > >> Thomas, could you please test it using nvptx > > It mostly ;-) works. With nvptx offloading enabled (which you don't > have, do you?), I'm seeing one test case regress: > > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 9) > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 13) > PASS: libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for excess errors) > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 execution test > > (Same for C++.) That testcase, just recently added by Tom in r233237 > "Handle -fdiagnostics-color in lto", specifies 'dg-additional-options > "-flto -fno-use-linker-plugin"'. Is that now an unsupported > combination/configuration? (I have not yet looked in detail, but it > appears as if the offloading compilers are no longer being run for > -fno-use-linker-plugin.) Yes, it's really hard to fix the "lto + non-lto objects" issue for no-use-linker-plugin LTO path. In this patch lto-plugin prepares a list of objects files with offloading and passes it to lto-wrapper, so I believe we should consider offloading without lto-plugin as unsupported. I'll update wiki when the patch will be committed. >> including the testcase with static >> libraries? > > Works in my manual testing if I work around the following issue: > >> --- a/gcc/config/gnu-user.h >> +++ b/gcc/config/gnu-user.h >> @@ -49,14 +49,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see >> %{" NO_PIE_SPEC ":crtbegin.o%s}} \ >> %{fvtable-verify=none:%s; \ >> fvtable-verify=preinit:vtv_start_preinit.o%s; \ >> - fvtable-verify=std:vtv_start.o%s}" >> + fvtable-verify=std:vtv_start.o%s} \ >> + %{fopenacc|fopenmp:%:if-exists(crtoffloadbegin%O%s)}" > > (..., and similar for others.) The if-exists spec function only works > for absolute paths (I have not researched, why?), so it won't locate the > files for relative -Bbuild-gcc/[...] prefixes, and linking will fail: > > /tmp/ccGajPD4.crtoffloadtable.o:(.rodata+0x0): undefined reference to `__offload_func_table' > /tmp/ccGajPD4.crtoffloadtable.o:(.rodata+0x8): undefined reference to `__offload_funcs_end' > /tmp/ccGajPD4.crtoffloadtable.o:(.rodata+0x10): undefined reference to `__offload_var_table' > /tmp/ccGajPD4.crtoffloadtable.o:(.rodata+0x18): undefined reference to `__offload_vars_end' > > If I use the absolute -B$PWD/build-gcc/[...], it works. (But there is no > requirement for -B prefixes to be absolute, as far as I know.) Why not > make it a hard error, though, if these files are missing? Can we use > something like (untested pseudo-patch): > > +#ifdef ENABLE_OFFLOADING > +# define CRTOFFLOADBEGIN "%{fopenacc|fopenmp:%:crtoffloadbegin%O%s}" > +#else > +# define CRTOFFLOADBEGIN "" > +#endif > > @@ -49,14 +49,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > %{" NO_PIE_SPEC ":crtbegin.o%s}} \ > %{fvtable-verify=none:%s; \ > fvtable-verify=preinit:vtv_start_preinit.o%s; \ > - fvtable-verify=std:vtv_start.o%s}" > + fvtable-verify=std:vtv_start.o%s} \ > + " CRTOFFLOADBEGIN ")}" OK, I'll replace if-exists with ifdef ENABLE_OFFLOADING. > I have not verified your patch's logic in detail (arcane...) ;-) so just > two drive-by comments: > >> #else >> #define GNU_USER_TARGET_STARTFILE_SPEC \ >> "%{!shared: %{pg|p|profile:gcrt1.o%s;:crt1.o%s}} \ >> crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s} \ >> %{fvtable-verify=none:%s; \ >> fvtable-verify=preinit:vtv_start_preinit.o%s; \ >> - fvtable-verify=std:vtv_start.o%s}" >> + fvtable-verify=std:vtv_start.o%s} \ >> + %{fopenacc|fopenmp:%:if-exists(crtoffloadbegin%O%s)}" >> #endif >> #undef STARTFILE_SPEC >> #define STARTFILE_SPEC GNU_USER_TARGET_STARTFILE_SPEC >> @@ -73,13 +75,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see >> fvtable-verify=preinit:vtv_end_preinit.o%s; \ >> fvtable-verify=std:vtv_end.o%s} \ >> %{shared:crtendS.o%s;: %{" PIE_SPEC ":crtendS.o%s} \ >> - %{" NO_PIE_SPEC ":crtend.o%s}} crtn.o%s" >> + %{" NO_PIE_SPEC ":crtend.o%s}} crtn.o%s \ >> + %{fopenacc|fopenmp:%:if-exists(crtoffloadend%O%s)}" >> #else >> #define GNU_USER_TARGET_ENDFILE_SPEC \ >> "%{fvtable-verify=none:%s; \ >> fvtable-verify=preinit:vtv_end_preinit.o%s; \ >> fvtable-verify=std:vtv_end.o%s} \ >> - %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s" >> + %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s \ >> + %{fopenacc|fopenmp:%:if-exists(crtoffloadend%O%s)}" >> #endif >> #undef ENDFILE_SPEC >> #define ENDFILE_SPEC GNU_USER_TARGET_ENDFILE_SPEC > > I guess we currently don't have to care about offloading configurations > not using the gnu-user.h file in which you modified the > STARTFILE_SPEC/ENDFILE_SPEC? I think so. >> --- a/lto-plugin/lto-plugin.c >> +++ b/lto-plugin/lto-plugin.c > >> @@ -671,16 +681,37 @@ all_symbols_read_handler (void) > >> + if (num_offload_files > 0) >> { >> + [...] >> + struct plugin_offload_file *ofld; >> + [...] >> + ofld = offload_files->next; >> + while (ofld) >> + { >> + fprintf (f, "%s\n", ofld->name); >> + ofld = ofld->next; >> + } > > To the casual reader, skipping the first offload_files looks like a > off-by-one error, so I suggest you add a comment "Skip the dummy item at > the start of the list.", or similar. OK. -- Ilya
On 22/02/16 19:07, Ilya Verbin wrote: > 2016-02-22 18:13 GMT+03:00 Thomas Schwinge<thomas@codesourcery.com>: >> >On Sat, 20 Feb 2016 13:54:20 +0300, Ilya Verbin<iverbin@gmail.com> wrote: >>> >>On Fri, Feb 19, 2016 at 15:53:08 +0100, Jakub Jelinek wrote: >>>> >> >On Wed, Feb 10, 2016 at 08:19:34PM +0300, Ilya Verbin wrote: >>>>> >> > >This patch adds crtoffload{begin,end}.o to all -fopenmp programs, if they exist. >>>>> >> > >I couldn't think of a better solution... >>>>> >> > >Tested using the testcase from the previous mail, e.g.: >>>>> >> > > >>>>> >> > >$ gcc -DNUM=1 -c -fopenmp test.c -o obj1.o >>>>> >> > >$ gcc -DNUM=2 -c -fopenmp test.c -o obj2.o >>>>> >> > >$ gcc -DNUM=3 -c -fopenmp test.c -o obj3.o >>>>> >> > >$ gcc -DNUM=4 -c -fopenmp test.c -o obj4.o -flto >>>>> >> > >$ gcc -DNUM=5 -c -fopenmp test.c -o obj5.o >>>>> >> > >$ gcc -DNUM=6 -c -fopenmp test.c -o obj6.o -flto >>>>> >> > >$ gcc -DNUM=7 -c -fopenmp test.c -o obj7.o >>>>> >> > >$ gcc-ar -cvq libtest.a obj3.o obj4.o obj5.o >>>>> >> > >$ gcc -fopenmp main.c obj1.o obj2.o libtest.a obj6.o obj7.o >>>>> >> > > >>>>> >> > >And other combinations. >> > >>> >>Thomas, could you please test it using nvptx >> > >> >It mostly;-) works. With nvptx offloading enabled (which you don't >> >have, do you?), I'm seeing one test case regress: >> > >> > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 9) >> > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 13) >> > PASS: libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for excess errors) >> > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 execution test >> > >> >(Same for C++.) That testcase, just recently added by Tom in r233237 >> >"Handle -fdiagnostics-color in lto", specifies 'dg-additional-options >> >"-flto -fno-use-linker-plugin"'. Is that now an unsupported >> >combination/configuration? (I have not yet looked in detail, but it >> >appears as if the offloading compilers are no longer being run for >> >-fno-use-linker-plugin.) > Yes, it's really hard to fix the "lto + non-lto objects" issue for > no-use-linker-plugin LTO path. In this patch lto-plugin prepares a > list of objects files with offloading and passes it to lto-wrapper, so > I believe we should consider offloading without lto-plugin as > unsupported. I'll update wiki when the patch will be committed. > Shouldn't we error (or at least warn) then if we compile a file containing an offload construct with fopenacc/fopenmp and -fno-use-linker-plugin? Thanks, - Tom
Hi! On Tue, 23 Feb 2016 08:37:07 +0100, Tom de Vries <Tom_deVries@mentor.com> wrote: > On 22/02/16 19:07, Ilya Verbin wrote: > > 2016-02-22 18:13 GMT+03:00 Thomas Schwinge<thomas@codesourcery.com>: > >> >On Sat, 20 Feb 2016 13:54:20 +0300, Ilya Verbin<iverbin@gmail.com> wrote: > >>> >>On Fri, Feb 19, 2016 at 15:53:08 +0100, Jakub Jelinek wrote: > >>>> >> >On Wed, Feb 10, 2016 at 08:19:34PM +0300, Ilya Verbin wrote: > >>>>> >> > >This patch adds crtoffload{begin,end}.o to all -fopenmp programs, if they exist. > >>> >>Thomas, could you please test it using nvptx > >> > > >> >It mostly;-) works. With nvptx offloading enabled (which you don't > >> >have, do you?), I'm seeing one test case regress: > >> > > >> > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 9) > >> > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 13) > >> > PASS: libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for excess errors) > >> > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 execution test > >> > > >> >(Same for C++.) That testcase, just recently added by Tom in r233237 > >> >"Handle -fdiagnostics-color in lto", specifies 'dg-additional-options > >> >"-flto -fno-use-linker-plugin"'. Is that now an unsupported > >> >combination/configuration? (I have not yet looked in detail, but it > >> >appears as if the offloading compilers are no longer being run for > >> >-fno-use-linker-plugin.) > > Yes, it's really hard to fix the "lto + non-lto objects" issue for > > no-use-linker-plugin LTO path. In this patch lto-plugin prepares a > > list of objects files with offloading and passes it to lto-wrapper, so > > I believe we should consider offloading without lto-plugin as > > unsupported. I'll update wiki when the patch will be committed. Aha, I see. I guess there's no point in keeping offloading supported for the -fno-lto (default) with -fno-use-linker-plugin configuration? Ilya, then please remove libgomp/testsuite/libgomp.oacc-c-c++-common/parallel-dims-2.c as part of your patch, unless Tom thinks it should be changed to a -flto test, but without -fno-use-linker-plugin? > Shouldn't we error (or at least warn) then if we compile a file > containing an offload construct with fopenacc/fopenmp and > -fno-use-linker-plugin? Yes, that makes sense to me, too. (Note that, as I understand it, -fno-use-linker-plugin may also be the default for certain GCC configurations...) Aside from spec stuff in gcc/gcc.c relating to LINK_PLUGIN_SPEC, I see there's some code in gcc/gcc.c:driver::maybe_run_linker evaluating the three possible values of HAVE_LTO_PLUGIN, but I have not yet thought about how and where to conditionalize the diagnostic if attempting to do offloading in an unsupported (-fno-use-linker-plugin) configuration. Grüße Thomas
On Wed, Feb 24, 2016 at 17:13:35 +0100, Thomas Schwinge wrote: > On Tue, 23 Feb 2016 08:37:07 +0100, Tom de Vries <Tom_deVries@mentor.com> wrote: > > On 22/02/16 19:07, Ilya Verbin wrote: > > > 2016-02-22 18:13 GMT+03:00 Thomas Schwinge<thomas@codesourcery.com>: > > >> >On Sat, 20 Feb 2016 13:54:20 +0300, Ilya Verbin<iverbin@gmail.com> wrote: > > >>> >>On Fri, Feb 19, 2016 at 15:53:08 +0100, Jakub Jelinek wrote: > > >>>> >> >On Wed, Feb 10, 2016 at 08:19:34PM +0300, Ilya Verbin wrote: > > >>>>> >> > >This patch adds crtoffload{begin,end}.o to all -fopenmp programs, if they exist. > > > >>> >>Thomas, could you please test it using nvptx > > >> > > > >> >It mostly;-) works. With nvptx offloading enabled (which you don't > > >> >have, do you?), I'm seeing one test case regress: > > >> > > > >> > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 9) > > >> > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for errors, line 13) > > >> > PASS: libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 (test for excess errors) > > >> > [-PASS:-]{+FAIL:+} libgomp.oacc-c/../libgomp.oacc-c-c++-common/parallel-dims-2.c -DACC_DEVICE_TYPE_nvidia=1 -DACC_MEM_SHARED=0 execution test > > >> > > > >> >(Same for C++.) That testcase, just recently added by Tom in r233237 > > >> >"Handle -fdiagnostics-color in lto", specifies 'dg-additional-options > > >> >"-flto -fno-use-linker-plugin"'. Is that now an unsupported > > >> >combination/configuration? (I have not yet looked in detail, but it > > >> >appears as if the offloading compilers are no longer being run for > > >> >-fno-use-linker-plugin.) > > > Yes, it's really hard to fix the "lto + non-lto objects" issue for > > > no-use-linker-plugin LTO path. In this patch lto-plugin prepares a > > > list of objects files with offloading and passes it to lto-wrapper, so > > > I believe we should consider offloading without lto-plugin as > > > unsupported. I'll update wiki when the patch will be committed. > > Aha, I see. I guess there's no point in keeping offloading supported for > the -fno-lto (default) with -fno-use-linker-plugin configuration? > > Ilya, then please remove > libgomp/testsuite/libgomp.oacc-c-c++-common/parallel-dims-2.c as part of > your patch, unless Tom thinks it should be changed to a -flto test, but > without -fno-use-linker-plugin? OK. > > Shouldn't we error (or at least warn) then if we compile a file > > containing an offload construct with fopenacc/fopenmp and > > -fno-use-linker-plugin? > > Yes, that makes sense to me, too. (Note that, as I understand it, > -fno-use-linker-plugin may also be the default for certain GCC > configurations...) Aside from spec stuff in gcc/gcc.c relating to > LINK_PLUGIN_SPEC, I see there's some code in > gcc/gcc.c:driver::maybe_run_linker evaluating the three possible values > of HAVE_LTO_PLUGIN, but I have not yet thought about how and where to > conditionalize the diagnostic if attempting to do offloading in an > unsupported (-fno-use-linker-plugin) configuration. To print this error someone has to detect that at least one object contains offload sections, only linker plugin and lto-wrapper can do it. But if linker plugin is absent, the lto-wrapper have to open all objects, scan for all sections, etc. Looks like too much overhead for a single diagnostic. -- Ilya
diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h index 2f1bbcc..2fdb63c 100644 --- a/gcc/config/gnu-user.h +++ b/gcc/config/gnu-user.h @@ -49,14 +49,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see %{" NO_PIE_SPEC ":crtbegin.o%s}} \ %{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_start_preinit.o%s; \ - fvtable-verify=std:vtv_start.o%s}" + fvtable-verify=std:vtv_start.o%s} \ + %{fopenacc|fopenmp:%:if-exists(crtoffloadbegin%O%s)}" #else #define GNU_USER_TARGET_STARTFILE_SPEC \ "%{!shared: %{pg|p|profile:gcrt1.o%s;:crt1.o%s}} \ crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s} \ %{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_start_preinit.o%s; \ - fvtable-verify=std:vtv_start.o%s}" + fvtable-verify=std:vtv_start.o%s} \ + %{fopenacc|fopenmp:%:if-exists(crtoffloadbegin%O%s)}" #endif #undef STARTFILE_SPEC #define STARTFILE_SPEC GNU_USER_TARGET_STARTFILE_SPEC @@ -73,13 +75,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see fvtable-verify=preinit:vtv_end_preinit.o%s; \ fvtable-verify=std:vtv_end.o%s} \ %{shared:crtendS.o%s;: %{" PIE_SPEC ":crtendS.o%s} \ - %{" NO_PIE_SPEC ":crtend.o%s}} crtn.o%s" + %{" NO_PIE_SPEC ":crtend.o%s}} crtn.o%s \ + %{fopenacc|fopenmp:%:if-exists(crtoffloadend%O%s)}" #else #define GNU_USER_TARGET_ENDFILE_SPEC \ "%{fvtable-verify=none:%s; \ fvtable-verify=preinit:vtv_end_preinit.o%s; \ fvtable-verify=std:vtv_end.o%s} \ - %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s" + %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s \ + %{fopenacc|fopenmp:%:if-exists(crtoffloadend%O%s)}" #endif #undef ENDFILE_SPEC #define ENDFILE_SPEC GNU_USER_TARGET_ENDFILE_SPEC diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index ed20b4e..f240812 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -68,7 +68,7 @@ static unsigned int nr; static char **input_names; static char **output_names; static char **offload_names; -static const char *offloadbegin, *offloadend; +static char *offload_objects_file_name; static char *makefile; const char tool_name[] = "lto-wrapper"; @@ -84,6 +84,8 @@ tool_cleanup (bool) maybe_unlink (ltrans_output_file); if (flto_out) maybe_unlink (flto_out); + if (offload_objects_file_name) + maybe_unlink (offload_objects_file_name); if (makefile) maybe_unlink (makefile); for (i = 0; i < nr; ++i) @@ -840,40 +842,32 @@ copy_file (const char *dest, const char *src) } } -/* Find the crtoffloadbegin.o and crtoffloadend.o files in LIBRARY_PATH, make - copies and store the names of the copies in offloadbegin and offloadend. */ +/* Find the crtoffloadtable.o file in LIBRARY_PATH, make copy and pass name of + the copy to the linker. */ static void -find_offloadbeginend (void) +find_crtoffloadtable (void) { char **paths = NULL; const char *library_path = getenv ("LIBRARY_PATH"); if (!library_path) return; - unsigned n_paths = parse_env_var (library_path, &paths, "/crtoffloadbegin.o"); + unsigned n_paths = parse_env_var (library_path, &paths, "/crtoffloadtable.o"); unsigned i; for (i = 0; i < n_paths; i++) if (access_check (paths[i], R_OK) == 0) { - size_t len = strlen (paths[i]); - char *tmp = xstrdup (paths[i]); - strcpy (paths[i] + len - strlen ("begin.o"), "end.o"); - if (access_check (paths[i], R_OK) != 0) - fatal_error (input_location, - "installation error, can't find crtoffloadend.o"); - /* The linker will delete the filenames we give it, so make - copies. */ - offloadbegin = make_temp_file (".o"); - offloadend = make_temp_file (".o"); - copy_file (offloadbegin, tmp); - copy_file (offloadend, paths[i]); - free (tmp); + /* The linker will delete the filename we give it, so make a copy. */ + char *crtoffloadtable = make_temp_file (".crtoffloadtable.o"); + copy_file (crtoffloadtable, paths[i]); + printf ("%s\n", crtoffloadtable); + XDELETEVEC (crtoffloadtable); break; } if (i == n_paths) fatal_error (input_location, - "installation error, can't find crtoffloadbegin.o"); + "installation error, can't find crtoffloadtable.o"); free_array_of_ptrs ((void **) paths, n_paths); } @@ -970,8 +964,8 @@ run_gcc (unsigned argc, char *argv[]) int new_head_argc; bool have_lto = false; bool have_offload = false; - unsigned lto_argc = 0, offload_argc = 0; - char **lto_argv, **offload_argv; + unsigned lto_argc = 0; + char **lto_argv; /* Get the driver and options. */ collect_gcc = getenv ("COLLECT_GCC"); @@ -987,10 +981,9 @@ run_gcc (unsigned argc, char *argv[]) &decoded_options, &decoded_options_count); - /* Allocate arrays for input object files with LTO or offload IL, + /* Allocate array for input object files with LTO IL, and for possible preceding arguments. */ lto_argv = XNEWVEC (char *, argc); - offload_argv = XNEWVEC (char *, argc); /* Look at saved options in the IL files. */ for (i = 1; i < argc; ++i) @@ -1002,6 +995,15 @@ run_gcc (unsigned argc, char *argv[]) int consumed; char *filename = argv[i]; + if (strncmp (argv[i], "-foffload-objects=", + sizeof ("-foffload-objects=") - 1) == 0) + { + have_offload = true; + offload_objects_file_name + = argv[i] + sizeof ("-foffload-objects=") - 1; + continue; + } + if ((p = strrchr (argv[i], '@')) && p != argv[i] && sscanf (p, "@%li%n", &loffset, &consumed) >= 1 @@ -1026,15 +1028,6 @@ run_gcc (unsigned argc, char *argv[]) have_lto = true; lto_argv[lto_argc++] = argv[i]; } - - if (find_and_merge_options (fd, file_offset, OFFLOAD_SECTION_NAME_PREFIX, - &offload_fdecoded_options, - &offload_fdecoded_options_count, collect_gcc)) - { - have_offload = true; - offload_argv[offload_argc++] = argv[i]; - } - close (fd); } @@ -1133,47 +1126,102 @@ run_gcc (unsigned argc, char *argv[]) if (have_offload) { - compile_images_for_offload_targets (offload_argc, offload_argv, + unsigned i, num_offload_files; + char **offload_argv; + FILE *f; + + f = fopen (offload_objects_file_name, "r"); + if (f == NULL) + fatal_error (input_location, "cannot open %s: %m", + offload_objects_file_name); + if (fscanf (f, "%u ", &num_offload_files) != 1) + fatal_error (input_location, "cannot read %s: %m", + offload_objects_file_name); + offload_argv = XCNEWVEC (char *, num_offload_files); + + /* Read names of object files with offload. */ + for (i = 0; i < num_offload_files; i++) + { + const unsigned piece = 32; + char *buf, *filename = XNEWVEC (char, piece); + size_t len; + + buf = filename; +cont1: + if (!fgets (buf, piece, f)) + break; + len = strlen (filename); + if (filename[len - 1] != '\n') + { + filename = XRESIZEVEC (char, filename, len + piece); + buf = filename + len; + goto cont1; + } + filename[len - 1] = '\0'; + offload_argv[i] = filename; + } + fclose (f); + if (offload_argv[num_offload_files - 1] == NULL) + fatal_error (input_location, "invalid format of %s", + offload_objects_file_name); + maybe_unlink (offload_objects_file_name); + offload_objects_file_name = NULL; + + /* Look at saved offload options in files. */ + for (i = 0; i < num_offload_files; i++) + { + char *p; + long loffset; + int fd, consumed; + off_t file_offset = 0; + char *filename = offload_argv[i]; + + if ((p = strrchr (offload_argv[i], '@')) + && p != offload_argv[i] + && sscanf (p, "@%li%n", &loffset, &consumed) >= 1 + && strlen (p) == (unsigned int) consumed) + { + filename = XNEWVEC (char, p - offload_argv[i] + 1); + memcpy (filename, offload_argv[i], p - offload_argv[i]); + filename[p - offload_argv[i]] = '\0'; + file_offset = (off_t) loffset; + } + fd = open (filename, O_RDONLY | O_BINARY); + if (fd == -1) + fatal_error (input_location, "cannot open %s: %m", filename); + if (!find_and_merge_options (fd, file_offset, + OFFLOAD_SECTION_NAME_PREFIX, + &offload_fdecoded_options, + &offload_fdecoded_options_count, + collect_gcc)) + fatal_error (input_location, "cannot read %s: %m", filename); + close (fd); + if (filename != offload_argv[i]) + XDELETEVEC (filename); + } + + compile_images_for_offload_targets (num_offload_files, offload_argv, offload_fdecoded_options, offload_fdecoded_options_count, decoded_options, decoded_options_count); + + free_array_of_ptrs ((void **) offload_argv, num_offload_files); + if (offload_names) { - find_offloadbeginend (); + find_crtoffloadtable (); for (i = 0; offload_names[i]; i++) printf ("%s\n", offload_names[i]); free_array_of_ptrs ((void **) offload_names, i); } } - if (offloadbegin) - printf ("%s\n", offloadbegin); - /* If object files contain offload sections, but do not contain LTO sections, then there is no need to perform a link-time recompilation, i.e. lto-wrapper is used only for a compilation of offload images. */ if (have_offload && !have_lto) - { - for (i = 1; i < argc; ++i) - if (strncmp (argv[i], "-fresolution=", - sizeof ("-fresolution=") - 1) != 0 - && strncmp (argv[i], "-flinker-output=", - sizeof ("-flinker-output=") - 1) != 0) - { - char *out_file; - /* Can be ".o" or ".so". */ - char *ext = strrchr (argv[i], '.'); - if (ext == NULL) - out_file = make_temp_file (""); - else - out_file = make_temp_file (ext); - /* The linker will delete the files we give it, so make copies. */ - copy_file (out_file, argv[i]); - printf ("%s\n", out_file); - } - goto finish; - } + goto finish; if (lto_mode == LTO_MODE_LTO) { @@ -1402,11 +1450,7 @@ cont: } finish: - if (offloadend) - printf ("%s\n", offloadend); - XDELETE (lto_argv); - XDELETE (offload_argv); obstack_free (&argv_obstack, NULL); } diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index 570b1a7..f09b39b 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -995,12 +995,16 @@ crtbeginT$(objext): $(srcdir)/crtstuff.c $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN -DCRTSTUFFT_O # crtoffloadbegin and crtoffloadend contain symbols, that mark the begin and -# the end of tables with addresses, required for offloading. +# the end of tables with addresses, required for offloading. crtoffloadtable +# contains the array with addresses of those symbols. crtoffloadbegin$(objext): $(srcdir)/offloadstuff.c $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN crtoffloadend$(objext): $(srcdir)/offloadstuff.c $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_END + +crtoffloadtable$(objext): $(srcdir)/offloadstuff.c + $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_TABLE endif ifeq ($(enable_vtable_verify),yes) diff --git a/libgcc/configure b/libgcc/configure index de8c13c..f3f3605 100644 --- a/libgcc/configure +++ b/libgcc/configure @@ -4835,7 +4835,7 @@ fi if test x"$enable_offload_targets" != x; then - extra_parts="${extra_parts} crtoffloadbegin.o crtoffloadend.o" + extra_parts="${extra_parts} crtoffloadbegin.o crtoffloadend.o crtoffloadtable.o" fi # Check if Solaris/x86 linker supports ZERO terminator unwind entries. diff --git a/libgcc/configure.ac b/libgcc/configure.ac index 860a5f5..897259e 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -418,7 +418,7 @@ AC_SUBST(accel_dir_suffix) AC_SUBST(real_host_noncanonical) if test x"$enable_offload_targets" != x; then - extra_parts="${extra_parts} crtoffloadbegin.o crtoffloadend.o" + extra_parts="${extra_parts} crtoffloadbegin.o crtoffloadend.o crtoffloadtable.o" fi # Check if Solaris/x86 linker supports ZERO terminator unwind entries. diff --git a/libgcc/offloadstuff.c b/libgcc/offloadstuff.c index 45e89cf..a4ea3ac 100644 --- a/libgcc/offloadstuff.c +++ b/libgcc/offloadstuff.c @@ -40,23 +40,22 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "tm.h" #include "libgcc_tm.h" +#if defined(HAVE_GAS_HIDDEN) && defined(ENABLE_OFFLOADING) + #define OFFLOAD_FUNC_TABLE_SECTION_NAME ".gnu.offload_funcs" #define OFFLOAD_VAR_TABLE_SECTION_NAME ".gnu.offload_vars" #ifdef CRT_BEGIN -#if defined(HAVE_GAS_HIDDEN) && defined(ENABLE_OFFLOADING) const void *const __offload_func_table[0] __attribute__ ((__used__, visibility ("hidden"), section (OFFLOAD_FUNC_TABLE_SECTION_NAME))) = { }; const void *const __offload_var_table[0] __attribute__ ((__used__, visibility ("hidden"), section (OFFLOAD_VAR_TABLE_SECTION_NAME))) = { }; -#endif #elif defined CRT_END -#if defined(HAVE_GAS_HIDDEN) && defined(ENABLE_OFFLOADING) const void *const __offload_funcs_end[0] __attribute__ ((__used__, visibility ("hidden"), section (OFFLOAD_FUNC_TABLE_SECTION_NAME))) = { }; @@ -64,8 +63,12 @@ const void *const __offload_vars_end[0] __attribute__ ((__used__, visibility ("hidden"), section (OFFLOAD_VAR_TABLE_SECTION_NAME))) = { }; +#elif defined CRT_TABLE + extern const void *const __offload_func_table[]; extern const void *const __offload_var_table[]; +extern const void *const __offload_funcs_end[]; +extern const void *const __offload_vars_end[]; const void *const __OFFLOAD_TABLE__[] __attribute__ ((__visibility__ ("hidden"))) = @@ -73,8 +76,9 @@ const void *const __OFFLOAD_TABLE__[] &__offload_func_table, &__offload_funcs_end, &__offload_var_table, &__offload_vars_end }; + +#else /* ! CRT_BEGIN && ! CRT_END && ! CRT_TABLE */ +#error "One of CRT_BEGIN, CRT_END or CRT_TABLE must be defined." #endif -#else /* ! CRT_BEGIN && ! CRT_END */ -#error "One of CRT_BEGIN or CRT_END must be defined." #endif diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c index 1ed0f08..35cb63a 100644 --- a/lto-plugin/lto-plugin.c +++ b/lto-plugin/lto-plugin.c @@ -129,6 +129,14 @@ struct plugin_file_info struct plugin_symtab conflicts; }; +/* List item with name of the file with offloading. */ + +struct plugin_offload_file +{ + char *name; + struct plugin_offload_file *next; +}; + /* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from stdio file streams, we do simple label translation here. */ @@ -152,8 +160,16 @@ static ld_plugin_add_symbols add_symbols; static struct plugin_file_info *claimed_files = NULL; static unsigned int num_claimed_files = 0; -static struct plugin_file_info *offload_files = NULL; -static unsigned int num_offload_files = 0; +/* List of files with offloading. */ +static struct plugin_offload_file *offload_files; +/* Last file in the list. */ +static struct plugin_offload_file *offload_files_last; +/* Last non-archive file in the list. */ +static struct plugin_offload_file *offload_files_last_obj; +/* Last LTO file in the list. */ +static struct plugin_offload_file *offload_files_last_lto; +/* Total number of files with offloading. */ +static unsigned num_offload_files; static char **output_files = NULL; static unsigned int num_output_files = 0; @@ -351,14 +367,6 @@ free_2 (void) free (info->name); } - for (i = 0; i < num_offload_files; i++) - { - struct plugin_file_info *info = &offload_files[i]; - struct plugin_symtab *symtab = &info->symtab; - free (symtab->aux); - free (info->name); - } - for (i = 0; i < num_output_files; i++) free (output_files[i]); free (output_files); @@ -367,8 +375,12 @@ free_2 (void) claimed_files = NULL; num_claimed_files = 0; - free (offload_files); - offload_files = NULL; + while (offload_files) + { + struct plugin_offload_file *ofld = offload_files; + offload_files = offload_files->next; + free (ofld); + } num_offload_files = 0; free (arguments_file_name); @@ -625,8 +637,7 @@ static enum ld_plugin_status all_symbols_read_handler (void) { unsigned i; - unsigned num_lto_args - = num_claimed_files + num_offload_files + lto_wrapper_num_args + 2; + unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 3; char **lto_argv; const char *linker_output_str = NULL; const char **lto_arg_ptr; @@ -646,7 +657,6 @@ all_symbols_read_handler (void) write_resolution (); free_1 (claimed_files, num_claimed_files); - free_1 (offload_files, num_offload_files); for (i = 0; i < lto_wrapper_num_args; i++) *lto_arg_ptr++ = lto_wrapper_argv[i]; @@ -671,16 +681,37 @@ all_symbols_read_handler (void) break; } *lto_arg_ptr++ = xstrdup (linker_output_str); - for (i = 0; i < num_claimed_files; i++) + + if (num_offload_files > 0) { - struct plugin_file_info *info = &claimed_files[i]; + FILE *f; + char *arg; + char *offload_objects_file_name; + struct plugin_offload_file *ofld; + + offload_objects_file_name = make_temp_file (".ofldlist"); + check (offload_objects_file_name, LDPL_FATAL, + "Failed to generate a temporary file name"); + f = fopen (offload_objects_file_name, "w"); + check (f, LDPL_FATAL, "could not open file with offload objects"); + fprintf (f, "%u\n", num_offload_files); + + ofld = offload_files->next; + while (ofld) + { + fprintf (f, "%s\n", ofld->name); + ofld = ofld->next; + } + fclose (f); - *lto_arg_ptr++ = info->name; + arg = concat ("-foffload-objects=", offload_objects_file_name, NULL); + check (arg, LDPL_FATAL, "could not allocate"); + *lto_arg_ptr++ = arg; } - for (i = 0; i < num_offload_files; i++) + for (i = 0; i < num_claimed_files; i++) { - struct plugin_file_info *info = &offload_files[i]; + struct plugin_file_info *info = &claimed_files[i]; *lto_arg_ptr++ = info->name; } @@ -1007,18 +1038,72 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed) xrealloc (claimed_files, num_claimed_files * sizeof (struct plugin_file_info)); claimed_files[num_claimed_files - 1] = lto_file; + + *claimed = 1; } - if (obj.found == 0 && obj.offload == 1) + if (offload_files == NULL) { - num_offload_files++; - offload_files = - xrealloc (offload_files, - num_offload_files * sizeof (struct plugin_file_info)); - offload_files[num_offload_files - 1] = lto_file; + /* Add dummy item to the start of the list. */ + offload_files = xmalloc (sizeof (struct plugin_offload_file)); + offload_files->name = NULL; + offload_files->next = NULL; + offload_files_last = offload_files; } - *claimed = 1; + /* If this is an LTO file without offload, and it is the first LTO file, save + the pointer to the last offload file in the list. Further offload LTO + files will be inserted after it, if any. */ + if (*claimed && obj.offload == 0 && offload_files_last_lto == NULL) + offload_files_last_lto = offload_files_last; + + if (obj.offload == 1) + { + /* Add file to the list. The order must be exactly the same as the final + order after recompilation and linking, otherwise host and target tables + with addresses wouldn't match. If a static library contains both LTO + and non-LTO objects, ld and gold link them in a different order. */ + struct plugin_offload_file *ofld + = xmalloc (sizeof (struct plugin_offload_file)); + ofld->name = lto_file.name; + ofld->next = NULL; + + if (*claimed && offload_files_last_lto == NULL && file->offset != 0 + && gold_version == -1) + { + /* ld only: insert first LTO file from the archive after the last real + object file immediately preceding the archive, or at the begin of + the list if there was no real objects before archives. */ + if (offload_files_last_obj != NULL) + { + ofld->next = offload_files_last_obj->next; + offload_files_last_obj->next = ofld; + } + else + { + ofld->next = offload_files->next; + offload_files->next = ofld; + } + } + else if (*claimed && offload_files_last_lto != NULL) + { + /* Insert LTO file after the last LTO file in the list. */ + ofld->next = offload_files_last_lto->next; + offload_files_last_lto->next = ofld; + } + else + /* Add non-LTO file or first non-archive LTO file to the end of the + list. */ + offload_files_last->next = ofld; + + if (ofld->next == NULL) + offload_files_last = ofld; + if (file->offset == 0) + offload_files_last_obj = ofld; + if (*claimed) + offload_files_last_lto = ofld; + num_offload_files++; + } goto cleanup;