[24/25] Ignore LLVM's blank lines.

Message ID 58748b9db7927f39a5740f42e7c30386d61a4080.1536144068.git.ams@codesourcery.com
State Superseded
Headers show
Series
  • AMD GCN Port
Related show

Commit Message

Andrew Stubbs Sept. 5, 2018, 11:52 a.m.
The GCN toolchain must use the LLVM assembler and linker because there's no
binutils port.  The LLVM tools do not have the same diagnostic style as
binutils, so the "blank line(s) in output" tests are inappropriate (and very
noisy).

The LLVM tools also have different command line options, so it's not possible
to autodetect object formats in the same way.

This patch addresses both issues.

2018-09-05  Andrew Stubbs  <ams@codesourcery.com>

	gcc/testsuite/
	* lib/file-format.exp (gcc_target_object_format): Handle AMD GCN.
	* lib/gcc-dg.exp (gcc-dg-prune): Ignore blank lines from the LLVM
	linker.
	* lib/target-supports.exp (check_effective_target_llvm_binutils): New.
---
 gcc/testsuite/lib/file-format.exp     |  3 +++
 gcc/testsuite/lib/gcc-dg.exp          |  2 +-
 gcc/testsuite/lib/target-supports.exp | 14 ++++++++++++++
 3 files changed, 18 insertions(+), 1 deletion(-)

Comments

Jeff Law Sept. 14, 2018, 4:18 p.m. | #1
On 9/5/18 5:52 AM, ams@codesourcery.com wrote:
> 

> The GCN toolchain must use the LLVM assembler and linker because there's no

> binutils port.  The LLVM tools do not have the same diagnostic style as

> binutils, so the "blank line(s) in output" tests are inappropriate (and very

> noisy).

> 

> The LLVM tools also have different command line options, so it's not possible

> to autodetect object formats in the same way.

> 

> This patch addresses both issues.

> 

> 2018-09-05  Andrew Stubbs  <ams@codesourcery.com>

> 

> 	gcc/testsuite/

> 	* lib/file-format.exp (gcc_target_object_format): Handle AMD GCN.

> 	* lib/gcc-dg.exp (gcc-dg-prune): Ignore blank lines from the LLVM

> 	linker.

> 	* lib/target-supports.exp (check_effective_target_llvm_binutils): New.

This is fine.  It's a NOP for other targets, so feel free to commit when
it's convenient for you.

jeff
Thomas Schwinge March 23, 2020, 3:29 p.m. | #2
Hi!

Now that I'm looking into enabling AMD GCN offloading in my builds, I
have a few concerns here.  ;-)

On 2018-09-14T10:18:12-0600, Jeff Law <law@redhat.com> wrote:
> On 9/5/18 5:52 AM, ams@codesourcery.com wrote:

>>

>> The GCN toolchain must use the LLVM assembler and linker because there's no

>> binutils port.  The LLVM tools do not have the same diagnostic style as

>> binutils


For reference:
'libgomp.c++/../libgomp.c-c++-common/function-not-offloaded.c', for
example:

    ld: error: undefined symbol: foo()
    >>> referenced by /tmp/ccNzknBD.o:(main._omp_fn.0)

    >>> referenced by /tmp/ccNzknBD.o:(main._omp_fn.0)


    ld: error: undefined symbol: __gxx_personality_v0
    >>> referenced by /tmp/ccNzknBD.o:(.data+0x13)

    collect2: error: ld returned 1 exit status
    mkoffload: fatal error: [...]/build-gcc/./gcc/x86_64-pc-linux-gnu-accel-amdgcn-amdhsa-gcc returned 1 exit status

Note the blank line between the two "diagnostic blocks".

>> so the "blank line(s) in output" tests are inappropriate (and very

>> noisy).


>>      gcc/testsuite/


>>      * lib/gcc-dg.exp (gcc-dg-prune): Ignore blank lines from the LLVM

>>      linker.

>>      * lib/target-supports.exp (check_effective_target_llvm_binutils): New.


> This is fine.  It's a NOP for other targets, so feel free to commit when

> it's convenient for you.


See below, is it really "a NOP for other targets"?

| --- a/gcc/testsuite/lib/gcc-dg.exp
| +++ b/gcc/testsuite/lib/gcc-dg.exp
| @@ -361,7 +361,7 @@ proc gcc-dg-prune { system text } {
|
|      # Complain about blank lines in the output (PR other/69006)
|      global allow_blank_lines
| -    if { !$allow_blank_lines } {
| +    if { !$allow_blank_lines && ![check_effective_target_llvm_binutils]} {
|       set num_blank_lines [llength [regexp -all -inline "\n\n" $text]]
|       if { $num_blank_lines } {
|           global testname_with_flags

(That got re-worked a bit, per <https://gcc.gnu.org/PR88920>.)

| --- a/gcc/testsuite/lib/target-supports.exp
| +++ b/gcc/testsuite/lib/target-supports.exp
| @@ -9129,6 +9129,14 @@ proc check_effective_target_offload_hsa { } {
|      } "-foffload=hsa" ]
|  }
|
| +# Return 1 if the compiler has been configured with hsa offloading.

(Is this conceptually really appropriate to have here in
'gcc/testsuite/', given that all 'mkoffload'-based offloading testing
happens in libgomp only?)  (And, 'hsa' copy'n'pasto should be 'amdgcn'?)

| +
| +proc check_effective_target_offload_gcn { } {
| +    return [check_no_compiler_messages offload_gcn assembly {
| +     int main () {return 0;}
| +    } "-foffload=amdgcn-unknown-amdhsa" ]
| +}

This is too specific: "amdgcn-unknown-amdhsa" is often spelled just
"amdgcn-amdhsa", for example.

Our current '-foffload' syntax is not amenable to such variations; we
really need to re-work that.  (That's also one of the reasons why
<https://gcc.gnu.org/PR67300> "-foffload* undocumented" is still open,
and hasn't seen any further work: the '-foffload' as we've currently got
it implemented is somewhat useful, yes, but needs to be improved to be
really useful for users -- as well as for ourselves, as we're seeing
here.)  For example, consider you'd like to do offloading compilation to
include code for two different AMD GCN ISAs (fat binaries).  Or, once
that is supported for OpenACC, "offloading" to several different
multicore CPU ISAs/variations.  Can't specify such things given the
current syntax; we need some kind of abstraction from offload target.
(But that's a separate discussion, of course.)

Anyway, per the current code here, if instead of amdgcn-unknown-amdhsa I
configure GCC for amdgcn-amdhsa offload target, this test will not work.

| +# Return 1 if this target uses an LLVM assembler and/or linker
| +proc check_effective_target_llvm_binutils { } {
| +    return [expr { [istarget amdgcn*-*-*]
| +                || [check_effective_target_offload_gcn] } ]
| +}

Unless I'm understanding something wrong, this (second condition here)
means that all the checking added for <https://gcc.gnu.org/PR69006>
"Extraneous newline emitted between error messages in GCC 6" will be void
as soon as GCC is configured for AMD GCN offloading.  (This
effective-target here doesn't just apply to AMD GCN offloading
compliation, but to *all* standard GCC testsuite checking, doesn't it?)
That seems problematic to me: conceptually, but also in practice, given
that more and more users (for example, major GNU/Linux distributions) are
enabling GCC offloading compilation.


So here is a different proposal.  The problem we're having is that the
AMD GCN 'as' (that is, 'llvm-mc') prints "unsuitable" diagnostics (as
quoted at the top of my email).

How about having a simple wrapper around it, to post-process its 'stderr'
to remove any blank linkes between "diagnostic blocks"?  Then we could
remove this fragile 'check_effective_target_llvm_binutils' etc.?

I shall offer to implement the simple shell script, and suppose this
could live in 'gcc/config/gcn/'?  ("Just" need to figure out how to
integrate that into the GCC build process, top-level build system.)


Grüße
 Thomas
-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander Walter
Thomas Schwinge March 24, 2020, 9:05 p.m. | #3
Hi!

On 2020-03-23T16:29:40+0100, I wrote:
> On 2018-09-14T10:18:12-0600, Jeff Law <law@redhat.com> wrote:

>> On 9/5/18 5:52 AM, ams@codesourcery.com wrote:

>>>

>>> The GCN toolchain must use the LLVM assembler and linker because there's no

>>> binutils port.  The LLVM tools do not have the same diagnostic style as

>>> binutils

>

> For reference:

> 'libgomp.c++/../libgomp.c-c++-common/function-not-offloaded.c', for

> example:

>

>     ld: error: undefined symbol: foo()

>     >>> referenced by /tmp/ccNzknBD.o:(main._omp_fn.0)

>     >>> referenced by /tmp/ccNzknBD.o:(main._omp_fn.0)

>

>     ld: error: undefined symbol: __gxx_personality_v0

>     >>> referenced by /tmp/ccNzknBD.o:(.data+0x13)

>     collect2: error: ld returned 1 exit status

>     mkoffload: fatal error: [...]/build-gcc/./gcc/x86_64-pc-linux-gnu-accel-amdgcn-amdhsa-gcc returned 1 exit status

>

> Note the blank line between the two "diagnostic blocks".

>

>>> so the "blank line(s) in output" tests are inappropriate (and very

>>> noisy).


> So here is a different proposal.  The problem we're having is that the

> AMD GCN 'as' (that is, 'llvm-mc') prints "unsuitable" diagnostics (as

> quoted at the top of my email).


(No idea where I got the idea from that 'as' prints 'ld' error messages,
as displayed above...)  ;-) (But supposedly that problem applies to both,
or even generally all LLVM tools?)

> How about having a simple wrapper around it, to post-process its 'stderr'

> to remove any blank linkes between "diagnostic blocks"?  Then we could

> remove this fragile 'check_effective_target_llvm_binutils' etc.?

>

> I shall offer to implement the simple shell script, and suppose this

> could live in 'gcc/config/gcn/'?


I have implemented that, and it appears to generally work, but of
course...

> ("Just" need to figure out how to

> integrate that into the GCC build process, top-level build system.)


... this was the non-trivial bit, and may need some further thought --
which I can't allocate time for right now, so I'll postpone this for
later.  I'm attaching my "[WIP] 'llvm-tools-wrapper' [PR88920]" patch, in
case somebody would like to have a first look.


Grüße
 Thomas


-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander Walter
From 31c8828d37bed37b4ee4eb3bbefb8eb1db46e0a1 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>

Date: Tue, 24 Mar 2020 21:59:04 +0100
Subject: [PATCH] [WIP] 'llvm-tools-wrapper' [PR88920]

	PR testsuite/88920
---
 gcc/Makefile.in                               |   9 ++
 gcc/config.in                                 |   6 +
 gcc/configure                                 |  17 +++
 gcc/configure.ac                              |  12 ++
 gcc/doc/sourcebuild.texi                      |   6 -
 gcc/gcc.c                                     | 116 +++++++++++++++---
 gcc/llvm-tools-wrapper.in                     |  35 ++++++
 gcc/testsuite/lib/gcc-dg.exp                  |   4 -
 gcc/testsuite/lib/target-supports.exp         |  15 ---
 .../function-not-offloaded.c                  |   1 -
 10 files changed, 175 insertions(+), 46 deletions(-)
 create mode 100755 gcc/llvm-tools-wrapper.in

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index fa9923bb2703..4d13707453b2 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1974,6 +1974,7 @@ start.encap: native xgcc$(exeext) cpp$(exeext) specs \
 rest.encap: lang.rest.encap
 # This is what is made with the host's compiler
 # whether making a cross compiler or not.
+#TODO Do we need 'llvm-tools-wrapper' here?
 native: config.status auto-host.h build-@POSUB@ $(LANGUAGES) \
 	$(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext) \
 	gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext)
@@ -3525,6 +3526,10 @@ ifeq ($(enable_plugin),yes)
 install: install-plugin
 endif
 
+#TODO ifeq (TODO)
+install: install-llvm-tools-wrapper
+#TODO endif
+
 install-strip: override INSTALL_PROGRAM = $(INSTALL_STRIP_PROGRAM)
 ifneq ($(STRIP),)
 install-strip: STRIPPROG = $(STRIP)
@@ -3920,6 +3925,10 @@ install-gcc-ar: installdirs gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext)
 	  done; \
 	fi
 
+# Install llvm-tools-wrapper.
+install-llvm-tools-wrapper: llvm-tools-wrapper$(exeext)
+	$(INSTALL_PROGRAM) llvm-tools-wrapper$(exeext) $(DESTDIR)$(libexecsubdir)/llvm-tools-wrapper$(exeext)
+
 # Cancel installation by deleting the installed files.
 uninstall: lang.uninstall
 	-rm -rf $(DESTDIR)$(libsubdir)
diff --git a/gcc/config.in b/gcc/config.in
index 01fb18dbbb5a..ab51b9aef898 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -2042,6 +2042,12 @@
 #endif
 
 
+/* Define if using LLVM tools. */
+#ifndef USED_FOR_TARGET
+#undef LLVM_TOOLS_WRAPPER
+#endif
+
+
 /* Define to the name of the LTO plugin DSO that must be passed to the
    linker's -plugin=LIB option. */
 #ifndef USED_FOR_TARGET
diff --git a/gcc/configure b/gcc/configure
index 5381e107bce7..06f46c4bd6b0 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -22994,6 +22994,21 @@ else
 $as_echo "$gcc_cv_otool" >&6; }
 fi
 
+# Do we need the llvm-tools-wrapper?
+#TODO Make this a feature test, or is that good enough?
+case $target in
+  amdgcn*)
+
+$as_echo "#define LLVM_TOOLS_WRAPPER 1" >>confdefs.h
+
+    #TODO Does this need any 'Makefile.in' support for stating regeneration dependencies?
+    #TODO This is modelled after the 'exec-tool.in' stuff.
+    ac_config_files="$ac_config_files llvm-tools-wrapper:llvm-tools-wrapper.in"
+
+    ;;
+esac
+
+
 # Figure out what assembler alignment features are present.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler flags" >&5
 $as_echo_n "checking assembler flags... " >&6; }
@@ -31460,6 +31475,7 @@ do
     "as") CONFIG_FILES="$CONFIG_FILES as:exec-tool.in" ;;
     "collect-ld") CONFIG_FILES="$CONFIG_FILES collect-ld:exec-tool.in" ;;
     "nm") CONFIG_FILES="$CONFIG_FILES nm:exec-tool.in" ;;
+    "llvm-tools-wrapper") CONFIG_FILES="$CONFIG_FILES llvm-tools-wrapper:llvm-tools-wrapper.in" ;;
     "clearcap.map") CONFIG_LINKS="$CONFIG_LINKS clearcap.map:${srcdir}/config/$clearcap_map" ;;
     "$all_outputs") CONFIG_FILES="$CONFIG_FILES $all_outputs" ;;
     "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
@@ -32094,6 +32110,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
     "as":F) chmod +x as ;;
     "collect-ld":F) chmod +x collect-ld ;;
     "nm":F) chmod +x nm ;;
+    "llvm-tools-wrapper":F) chmod +x llvm-tools-wrapper ;;
     "default":C)
 case ${CONFIG_HEADERS} in
   *auto-host.h:config.in*)
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 0d6230e0ca1b..0f3fcfefd4fc 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2685,6 +2685,18 @@ else
 	AC_MSG_RESULT($gcc_cv_otool)
 fi
 
+# Do we need the llvm-tools-wrapper?
+#TODO Make this a feature test, or is that good enough?
+case $target in
+  amdgcn*)
+    AC_DEFINE(LLVM_TOOLS_WRAPPER, 1, [Define if using LLVM tools.])
+    #TODO Does this need any 'Makefile.in' support for stating regeneration dependencies?
+    #TODO This is modelled after the 'exec-tool.in' stuff.
+    AC_CONFIG_FILES(llvm-tools-wrapper:llvm-tools-wrapper.in, [chmod +x llvm-tools-wrapper])
+    ;;
+esac
+
+
 # Figure out what assembler alignment features are present.
 gcc_GAS_CHECK_FEATURE([.balign and .p2align], gcc_cv_as_balign_and_p2align,
  [2,6,0],,
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index eef1432147ce..d6057656c6ef 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2333,9 +2333,6 @@ Target uses GNU @command{ld}.
 Target keeps null pointer checks, either due to the use of
 @option{-fno-delete-null-pointer-checks} or hardwired into the target.
 
-@item llvm_binutils
-Target is using an LLVM assembler and/or linker, instead of GNU Binutils.
-
 @item lto
 Compiler has been configured to support link-time optimization (LTO).
 
@@ -2363,9 +2360,6 @@ Target supports the @code{noinit} variable attribute.
 @item nonpic
 Target does not generate PIC by default.
 
-@item offload_gcn
-Target has been configured for OpenACC/OpenMP offloading on AMD GCN.
-
 @item pie_enabled
 Target generates PIE by default.
 
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 9f790db0daf4..eb0fb836ffc0 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -3038,11 +3038,18 @@ execute (void)
 
   gcc_assert (!processing_spec_function);
 
+  /* TODO Why is this wrapping here done "early", instead of "late", as done
+     for the 'valgrind' wrapping?  */
   if (wrapper_string)
     {
       string = find_a_file (&exec_prefixes,
 			    argbuf[0], X_OK, false);
       if (string)
+	/* This overwrites 'argbuf[0]', thus later 'commands[0].prog' is set to
+	   the resolved 'string' instead of the original 'argbuf[0]'.  This
+	   means that any special handling for 'argbuf[0]' can no longer be
+	   expected to work (such as when 'find_a_file' compares this to 'as'
+	   or 'ld').  */
 	argbuf[0] = string;
       insert_wrapper (wrapper_string);
     }
@@ -3064,6 +3071,7 @@ execute (void)
   commands[0].prog = argbuf[0]; /* first command.  */
   commands[0].argv = argbuf.address ();
 
+  /* TODO For 'wrapper_string', this has already been done above.  */
   if (!wrapper_string)
     {
       string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
@@ -3164,32 +3172,100 @@ execute (void)
 #endif /* DEBUG */
     }
 
-#ifdef ENABLE_VALGRIND_CHECKING
-  /* Run the each command through valgrind.  To simplify prepending the
-     path to valgrind and the option "-q" (for quiet operation unless
-     something triggers), we allocate a separate argv array.  */
-
+  /* Possibly run each command through a wrapper.  */
+  //TODO Why is this done after '-v' handling?
   for (i = 0; i < n_commands; i++)
     {
-      const char **argv;
-      int argc;
-      int j;
-
-      for (argc = 0; commands[i].argv[argc] != NULL; argc++)
-	;
+      size_t argc_wrap_llvm_tools_wrapper = 0;
+#ifdef LLVM_TOOLS_WRAPPER //TODO Conditional whether assembler (?TODO), linker (even separately?) are LLVM tools.
+      //TODO For offloading compilation (I haven't tried native yet), something isn't working: despite passing in '-fdiagnostics-color=never', the 'lld' wrapper invocation is still done with '-fdiagnostics-color=always' if printing to a terminal -- but does turn into '-fdiagnostics-color=never' if not printing to a terminal.
+      //TODO Does that mean that 'diagnostic_color_init' is only doing the 'DIAGNOSTICS_COLOR_DEFAULT' thing, but not paying attention to the command-line argument?
+      //TODO Per PR69707, that is supposed to be working?
+      //TODO Is that maybe a problem in 'mkoffload'?  (..., and if yes, just amdgcn, or all?)
+      const char *llvm_tools_wrapper_color_arg = NULL;
+#if 0 //TODO Do this for 'as', too?
+      if (!strcmp (commands[i].prog, "as"))
+	{
+	  /* That's 'llvm-mc'.  */
+	  argc_wrap_llvm_tools_wrapper = 1;
+	  if (pp_show_color (global_dc->printer))
+	    {
+	      argc_wrap_llvm_tools_wrapper += 1;
+	      llvm_tools_wrapper_color_arg = "--color";
+	    }
+	  else
+	    ; /* There doesn't seem to be a command-line flag to force-disable
+		 this, so let's hope the default does the right thing.  */
+	}
+      else
+#endif
+	if (!strcmp (commands[i].prog, linker_name_spec))
+        {
+	  /* That's 'lld'.  */
+	  argc_wrap_llvm_tools_wrapper = 1;
+	  if (pp_show_color (global_dc->printer))
+	    {
+	      argc_wrap_llvm_tools_wrapper += 1;
+	      llvm_tools_wrapper_color_arg = "--color-diagnostics=always";
+	    }
+	  else
+	    {
+	      argc_wrap_llvm_tools_wrapper += 1;
+	      llvm_tools_wrapper_color_arg = "--color-diagnostics=never";
+	    }
+	}
+#endif /* LLVM_TOOLS_WRAPPER */
+    size_t argc_wrap_valgrind = 0;
+#ifdef ENABLE_VALGRIND_CHECKING
+      argc_wrap_valgrind = 2;
+#endif
+      size_t argc_extra = argc_wrap_llvm_tools_wrapper + argc_wrap_valgrind;
+      if (argc_extra > 0)
+	{
+	  /* One extra for the terminator.  */
+	  argc_extra += 1;
 
-      argv = XALLOCAVEC (const char *, argc + 3);
+	  size_t argc;
+	  for (argc = 0; commands[i].argv[argc] != NULL; argc++)
+	    ;
 
-      argv[0] = VALGRIND_PATH;
-      argv[1] = "-q";
-      for (j = 2; j < argc + 2; j++)
-	argv[j] = commands[i].argv[j - 2];
-      argv[j] = NULL;
+	  const char **argv = XALLOCAVEC (const char *, argc_extra + argc);
+	  //TODO Where does this get deallocated?
 
-      commands[i].argv = argv;
-      commands[i].prog = argv[0];
-    }
+	  size_t j = 0;
+	  if (argc_wrap_llvm_tools_wrapper)
+	    {
+	      //TODO This uses 'find_a_file' to locate this in the build directory.  This supposedly should also work for the install tree.  'find_a_file' should be doing/supporting all that; this is modelled similar to 'lto-wrapper'.
+	      argv[j++] = find_a_file (&exec_prefixes, "llvm-tools-wrapper", X_OK, false);
+	    }
+	  if (argc_wrap_valgrind)
+	    {
+#ifdef ENABLE_VALGRIND_CHECKING
+	      /* Run the each command through valgrind.  */
+	      argv[j++] = VALGRIND_PATH;
+	      /* Request quiet operation unless something triggers.  */
+	      argv[j++] = "-q";
+#else
+	      gcc_unreachable ();
 #endif
+	    }
+	  /* Now the actual executable.  */
+	  argv[j++] = commands[i].argv[0];
+#ifdef LLVM_TOOLS_WRAPPER
+	  /* Now any LLVM tools color arguments.  */
+	  if (llvm_tools_wrapper_color_arg)
+	    argv[j++] = llvm_tools_wrapper_color_arg;
+#endif /* LLVM_TOOLS_WRAPPER */
+	  /* Now all other arguments.  */
+	  for (size_t arg = 1; arg < argc; ++arg)
+	    argv[j++] = commands[i].argv[arg];
+	  argv[j++] = NULL;
+	  gcc_checking_assert (j == argc + argc_extra);
+
+	  commands[i].argv = argv;
+	  commands[i].prog = argv[0];
+	}
+    }
 
   /* Run each piped subprocess.  */
 
diff --git a/gcc/llvm-tools-wrapper.in b/gcc/llvm-tools-wrapper.in
new file mode 100755
index 000000000000..a9233209082a
--- /dev/null
+++ b/gcc/llvm-tools-wrapper.in
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+
+# This is a simple wrapper that invokes '$@', and filters 'stderr' such as to
+# only print non-empty lines.
+
+# Doing this, the invoked program may notice that it's not printing to a
+# terminal, and may change its behavior, say, to disable color output.  If that
+# is a concern, it has to be addressed individually.
+
+# This implementation depends on the GNU Bash, in particular its 'coproc'
+# command.  We expect this wrapper only to be used on systems where such
+# dependencies are not a concern.
+
+set -e
+
+# Set up a coprocess: print non-empty lines to 'stderr'.
+coproc grep --line-buffered . >&2
+
+# Invoke '$@'.
+status=0
+"$@" 2>&"${COPROC[1]}" || status="$?"
+
+# Shut down the coprocess.
+# Apparently, per
+# <https://unix.stackexchange.com/questions/86270/how-do-you-use-the-command-coproc-in-various-shells>,
+# we have to use such an indirection ('coproc_fd_1') to support "bash versions
+# prior to 4.3".
+coproc_fd_1=${COPROC[1]}
+exec {coproc_fd_1}<&-
+# We intentionally do not 'wait' for '$COPROC_PID' here, as that sometimes
+# fails (perhaps if the coprocess has never been active, if there has been no
+# output at all?).
+wait
+
+exit "$status"
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index cccd3ce4742c..941fc72b5947 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -342,10 +342,6 @@ proc gcc-dg-test { prog do_what extra_tool_flags } {
 # for all tests.
 set allow_blank_lines 0
 
-if { [check_effective_target_llvm_binutils] } {
-    set allow_blank_lines 2
-}
-
 # A command for use by testcases to mark themselves as expecting
 # blank lines in the output.
 
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ca3895c22690..089ecfb68ad4 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -9514,14 +9514,6 @@ proc check_effective_target_offload_hsa { } {
     } "-foffload=hsa" ]
 }
 
-# Return 1 if the compiler has been configured with hsa offloading.
-
-proc check_effective_target_offload_gcn { } {
-    return [check_no_compiler_messages offload_gcn assembly {
-	int main () {return 0;}
-    } "-foffload=amdgcn-unknown-amdhsa" ]
-}
-
 # Return 1 if the target support -fprofile-update=atomic
 proc check_effective_target_profile_update_atomic {} {
     return [check_no_compiler_messages profile_update_atomic assembly {
@@ -9963,13 +9955,6 @@ foreach N {df} {
     }]
 }
 
-# Return 1 if this target uses an LLVM assembler and/or linker
-proc check_effective_target_llvm_binutils { } {
-    return [check_cached_effective_target llvm_binutils {
-	      expr { [istarget amdgcn*-*-*]
-		     || [check_effective_target_offload_gcn] }}]
-}
-
 # Return 1 if the compiler supports '-mfentry'.
 
 proc check_effective_target_mfentry { } {
diff --git a/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c b/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c
index f01a64e72c07..9e59ef8864e7 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/function-not-offloaded.c
@@ -1,6 +1,5 @@
 /* { dg-do link } */
 /* { dg-excess-errors "unresolved symbol foo, lto1, mkoffload and lto-wrapper fatal errors" { target offload_device_nonshared_as } } */
-/* { dg-allow-blank-lines-in-output 1 } */
 /* { dg-additional-sources "function-not-offloaded-aux.c" } */
 
 #pragma omp declare target
-- 
2.25.1

Patch

diff --git a/gcc/testsuite/lib/file-format.exp b/gcc/testsuite/lib/file-format.exp
index 5c47246..c595fe2 100644
--- a/gcc/testsuite/lib/file-format.exp
+++ b/gcc/testsuite/lib/file-format.exp
@@ -41,6 +41,9 @@  proc gcc_target_object_format { } {
     } elseif { [istarget *-*-aix*] } {
 	# AIX doesn't necessarily have objdump, so hand-code it.
 	set gcc_target_object_format_saved coff
+    } elseif { [istarget *-*-amdhsa*] } {
+	# AMD GCN uses LLVM objdump which is not CLI-compatible
+	set gcc_target_object_format_saved elf
     } else {
         set objdump_name [find_binutils_prog objdump]
         set open_file [open objfmtst.c w]
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index f5e6bef..7df348e 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -361,7 +361,7 @@  proc gcc-dg-prune { system text } {
 
     # Complain about blank lines in the output (PR other/69006)
     global allow_blank_lines
-    if { !$allow_blank_lines } {
+    if { !$allow_blank_lines && ![check_effective_target_llvm_binutils]} {
 	set num_blank_lines [llength [regexp -all -inline "\n\n" $text]]
 	if { $num_blank_lines } {
 	    global testname_with_flags
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 61442bd..1e627fa 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -9129,6 +9129,14 @@  proc check_effective_target_offload_hsa { } {
     } "-foffload=hsa" ]
 }
 
+# Return 1 if the compiler has been configured with hsa offloading.
+
+proc check_effective_target_offload_gcn { } {
+    return [check_no_compiler_messages offload_gcn assembly {
+	int main () {return 0;}
+    } "-foffload=amdgcn-unknown-amdhsa" ]
+}
+
 # Return 1 if the target support -fprofile-update=atomic
 proc check_effective_target_profile_update_atomic {} {
     return [check_no_compiler_messages profile_update_atomic assembly {
@@ -9427,3 +9435,9 @@  proc check_effective_target_cet { } {
 	}
     } "-O2" ]
 }
+
+# Return 1 if this target uses an LLVM assembler and/or linker
+proc check_effective_target_llvm_binutils { } {
+    return [expr { [istarget amdgcn*-*-*]
+		   || [check_effective_target_offload_gcn] } ]
+}