Bug 68463 - Offloading fails when some objects are compiled with LTO and some without
Summary: Offloading fails when some objects are compiled with LTO and some without
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: driver (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: ---
Assignee: jnorris
URL:
Keywords: lto, openacc, openmp
Depends on:
Blocks:
 
Reported: 2015-11-20 19:32 UTC by iverbin
Modified: 2016-06-21 14:44 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2015-11-30 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description iverbin 2015-11-20 19:32:43 UTC
The reproducer:

$ cat foo.c

void foo ()
{
  #pragma omp target
  ;
}

$ cat bar.c

void bar ()
{
  #pragma omp target
  ;
}

$ cat main.c

extern void foo ();
extern void bar ();

int main ()
{
  foo ();
  bar ();
  return 0;
}

$ gcc -c -fopenmp -flto foo.c
$ gcc -c -fopenmp bar.c main.c
$ gcc -fopenmp foo.o bar.o main.o

main.o: In function `main':
main.c:(.text+0x14): undefined reference to `bar'
collect2: error: ld returned 1 exit status

This happens because the linker plugin in claim_file_handler claims bar.o, and
linker just drops it, because linker considers bar.o as LTO object.
Without offload it claims only LTO objects, but now it claims objects with any
IR.  (Yes, offloading misuses lto-plugin and lto-wrapper a bit.)

And even worse, it fails with -foffload=disable, because we decided to stream-
out offload IR unconditionally:
https://gcc.gnu.org/ml/gcc-patches/2014-10/msg00628.html
So -foffload=disable only disables compilation of target images in lto-wrapper,
but objects are handled by linker plugin before that.

The first solution that comes to mind - do not claim objects, which contain
offload IR without LTO IR.  But this will cause run-time error:
"libgomp: Cannot map target functions or variables (expected 1, have 2)",
because lto-wrapper will surround only *.ltrans.o (derived from foo.o) with
crtoffload{begin,end}.o; and bar.o will be added at the end of the list of
objects from lto-wrapper.  But we need this order to get correct host table:
"crtoffloadbegin.o, *.ltrans.o, bar.o, crtoffloadend.o".
Here is a bit more about tables:
https://gcc.gnu.org/wiki/Offloading#Address_mapping_tables

Or maybe we should implement new linker offload-plugin with its offload-wrapper,
but I don't know how difficult it would be to support 2 plugins in the linkers,
and it really doesn't solve the issue with crtoffload{begin,end}.o placement.

Or maybe just print an error during linking that offloading doesn't support
mixing LTO and non-LTO objects (even if some of them doesn't have offload)?
Comment 1 Richard Biener 2015-11-23 09:25:57 UTC
> Or maybe just print an error during linking that offloading doesn't support
> mixing LTO and non-LTO objects (even if some of them doesn't have offload)?

That's the worst solution - having non-LTO objects is the whole point of
linker-plugin support.

I presume the same issue exists for GCC 5.
Comment 2 iverbin 2015-11-30 12:27:04 UTC
> I presume the same issue exists for GCC 5.
Yes.

It seems that we can fix this issue by passing a new option to lto-wrapper,
which will contain a list of object files with offload (or a filename with the
list).  It also will allow to remove some hacky code from lto-wrapper, like this
comparison: if (strncmp (argv[i], "-fresolution=", sizeof ("-fresolution=") ...

E.g., if there are 4 objects:
* obj1.o - non-LTO, offload;
* obj2.o - LTO, non-offload;
* obj3.o - non-LTO, non-offload;
* obj4.o - LTO, offload;

then linker plugin will claim only obj2.o and obj4.o, as it was intended.  So it
will call lto-wrapper by passing obj2.o and obj4.o as argv.  But additionally
linker plugin will pass something like: -foffload_objects="obj1.o,obj4.o".
lto-wrapper will perform LTO on objects from argv as usually, and additionally
compile target images using offload IR from obj1.o and obj4.o.
The tables also should match, because host table will consist of: pieces from
all LTO objects with offload + pieces from non-LTO objects with offload.  Just
need to reorder offload_objects correspondingly before passing them to the
targer compiler (obj4.o,obj1.o).
However in this case both obj1.o and obj4.o cannot be surrounded by
crtoffload{begin,end}.o, because lto-wrapper cannot place crtoffload* before or
after obj1.o, because it is unclaimed.  But I guess this can be fixed by
something like linker script, which will place sections from crtoffload* at the
begin/end of the final joint section.
Comment 3 rguenther@suse.de 2015-11-30 13:27:57 UTC
On Mon, 30 Nov 2015, iverbin at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68463
> 
> iverbin at gcc dot gnu.org changed:
> 
>            What    |Removed                     |Added
> ----------------------------------------------------------------------------
>              Status|UNCONFIRMED                 |NEW
>    Last reconfirmed|                            |2015-11-30
>                  CC|                            |bernds at gcc dot gnu.org,
>                    |                            |hubicka at gcc dot gnu.org,
>                    |                            |jakub at gcc dot gnu.org,
>                    |                            |rguenth at gcc dot gnu.org
>      Ever confirmed|0                           |1
> 
> --- Comment #2 from iverbin at gcc dot gnu.org ---
> > I presume the same issue exists for GCC 5.
> Yes.
> 
> It seems that we can fix this issue by passing a new option to lto-wrapper,
> which will contain a list of object files with offload (or a filename with the
> list).  It also will allow to remove some hacky code from lto-wrapper, like
> this
> comparison: if (strncmp (argv[i], "-fresolution=", sizeof ("-fresolution=") ...
> 
> E.g., if there are 4 objects:
> * obj1.o - non-LTO, offload;
> * obj2.o - LTO, non-offload;
> * obj3.o - non-LTO, non-offload;
> * obj4.o - LTO, offload;
> 
> then linker plugin will claim only obj2.o and obj4.o, as it was intended.  So
> it
> will call lto-wrapper by passing obj2.o and obj4.o as argv.  But additionally
> linker plugin will pass something like: -foffload_objects="obj1.o,obj4.o".
> lto-wrapper will perform LTO on objects from argv as usually, and additionally
> compile target images using offload IR from obj1.o and obj4.o.
> The tables also should match, because host table will consist of: pieces from
> all LTO objects with offload + pieces from non-LTO objects with offload.  Just
> need to reorder offload_objects correspondingly before passing them to the
> targer compiler (obj4.o,obj1.o).
> However in this case both obj1.o and obj4.o cannot be surrounded by
> crtoffload{begin,end}.o, because lto-wrapper cannot place crtoffload* before or
> after obj1.o, because it is unclaimed.  But I guess this can be fixed by
> something like linker script, which will place sections from crtoffload* at the
> begin/end of the final joint section.

Sounds like a sensible plan to me.  Not sure if I like 
-foffload-objects=a,b,c,d I'd have used a temporary list file and
-foffload-objects=/tmp/ccxxxha to avoid quoting issues.

Richard.
Comment 4 iverbin 2016-02-25 12:24:24 UTC
Author: iverbin
Date: Thu Feb 25 12:23:52 2016
New Revision: 233712

URL: https://gcc.gnu.org/viewcvs?rev=233712&root=gcc&view=rev
Log:
gcc/
	PR driver/68463
	* config/gnu-user.h (CRTOFFLOADBEGIN): Define.  Add crtoffloadbegin.o if
	offloading is enabled and -fopenacc or -fopenmp is specified.
	(CRTOFFLOADEND): Likewise.
	(GNU_USER_TARGET_STARTFILE_SPEC): Add CRTOFFLOADBEGIN.
	(GNU_USER_TARGET_ENDFILE_SPEC): Add CRTOFFLOADEND.
	* 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.
libgomp/
	PR driver/68463
	* testsuite/libgomp.oacc-c-c++-common/parallel-dims-2.c: Remove.
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.

Removed:
    trunk/libgomp/testsuite/libgomp.oacc-c-c++-common/parallel-dims-2.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/gnu-user.h
    trunk/gcc/lto-wrapper.c
    trunk/libgcc/ChangeLog
    trunk/libgcc/Makefile.in
    trunk/libgcc/configure
    trunk/libgcc/configure.ac
    trunk/libgcc/offloadstuff.c
    trunk/libgomp/ChangeLog
    trunk/lto-plugin/ChangeLog
    trunk/lto-plugin/lto-plugin.c
Comment 5 iverbin 2016-02-25 14:32:29 UTC
Fixed in GCC 6.
Comment 6 Thomas Schwinge 2016-05-11 14:12:33 UTC
Per <http://news.gmane.org/find-root.php?message_id=%3C573200B5.7050302%40codesourcery.com%3E>: PowerPC GNU/Linux target fixed on trunk in r236098; still needs to be fixed on gcc-6-branch.
Comment 7 jnorris 2016-05-16 13:48:18 UTC
Author: jnorris
Date: Mon May 16 13:47:47 2016
New Revision: 236287

URL: https://gcc.gnu.org/viewcvs?rev=236287&root=gcc&view=rev
Log:
	Backport from mainline r236098.
	2016-05-10  James Norris  <jnorris@codesourcery.com>

	PR driver/68463
	* config/rs6000/sysv4.h (CRTOFFLOADBEGIN): Define. Add crtoffloadbegin.o
	if offloading is enabled and -fopenacc or -fopenmp is specified.
	(CRTOFFLOADEND): Likewise.
	(STARTFILE_LINUX_SPEC): Add CRTOFFLOADBEGIN.
	(ENDFILE_LINUX_SPEC): Add CRTOFFLOADEND.

Modified:
    branches/gcc-6-branch/gcc/ChangeLog
    branches/gcc-6-branch/gcc/config/rs6000/sysv4.h
Comment 8 jnorris 2016-06-13 13:17:54 UTC
Author: jnorris
Date: Mon Jun 13 13:17:22 2016
New Revision: 237379

URL: https://gcc.gnu.org/viewcvs?rev=237379&root=gcc&view=rev
Log:
	Backport from mainline r236098.
	2016-05-10  James Norris  <jnorris@codesourcery.com>

	PR driver/68463
	* config/rs6000/sysv4.h (CRTOFFLOADBEGIN): Define. Add crtoffloadbegin.o
	if offloading is enabled and -fopenacc or -fopenmp is specified.
	(CRTOFFLOADEND): Likewise.
	(STARTFILE_LINUX_SPEC): Add CRTOFFLOADBEGIN.
	(ENDFILE_LINUX_SPEC): Add CRTOFFLOADEND.

Modified:
    branches/gomp-4_0-branch/gcc/ChangeLog.gomp
    branches/gomp-4_0-branch/gcc/config/rs6000/sysv4.h
Comment 9 jnorris 2016-06-21 14:44:56 UTC
Complete backporting.