diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index ceb6b995283eb6206e89cb23d3e5c30a6fdfade9..ed811d103a5734ccf8d8a95a55734afc571c459f 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1217,6 +1217,21 @@ If there is no message for that line or if the text of that message is
 not matched by @var{regexp} then the check fails and @var{comment} is
 included in the @code{FAIL} message.
 
+@item @{ dg-note @var{regexp} [@var{comment} [@{ target/xfail @var{selector} @} [@var{line}] ]] @}
+The line is expected to get a @samp{note} message.
+If there is no message for that line or if the text of that message is
+not matched by @var{regexp} then the check fails and @var{comment} is
+included in the @code{FAIL} message.
+
+By default, any @emph{excess} @samp{note} messages are pruned, meaning
+their appearance doesn't trigger @emph{excess errors}.
+However, if @samp{dg-note} is used at least once in a testcase,
+they're not pruned and instead must @emph{all} be handled explicitly.
+Thus, if looking for just single instances of messages with
+@samp{note: } prefixes without caring for all of them, use
+@samp{dg-message "note: [@dots{}]"} instead of @samp{dg-note}, or use
+@samp{dg-note} together with @samp{dg-prune-output "note: "}.
+
 @item @{ dg-bogus @var{regexp} [@var{comment} [@{ target/xfail @var{selector} @} [@var{line}] ]] @}
 This DejaGnu directive appears on a source line that should not get a
 message matching @var{regexp}, or else specifies the source line
@@ -1227,7 +1242,8 @@ targets.
 @item @{ dg-line @var{linenumvar} @}
 This DejaGnu directive sets the variable @var{linenumvar} to the line number of
 the source line.  The variable @var{linenumvar} can then be used in subsequent
-@code{dg-error}, @code{dg-warning}, @code{dg-message} and @code{dg-bogus}
+@code{dg-error}, @code{dg-warning}, @code{dg-message}, @code{dg-note}
+and @code{dg-bogus}
 directives.  For example:
 
 @smallexample
@@ -1239,7 +1255,9 @@ float a; /* @{ dg-error "conflicting types of" @} */
 @item @{ dg-excess-errors @var{comment} [@{ target/xfail @var{selector} @}] @}
 This DejaGnu directive indicates that the test is expected to fail due
 to compiler messages that are not handled by @samp{dg-error},
-@samp{dg-warning} or @samp{dg-bogus}.  For this directive @samp{xfail}
+@samp{dg-warning}, @code{dg-message}, @samp{dg-note} or
+@samp{dg-bogus}.
+For this directive @samp{xfail}
 has the same effect as @samp{target}.
 
 @item @{ dg-prune-output @var{regexp} @}
diff --git a/gcc/testsuite/g++.dg/lto/odr-1_0.C b/gcc/testsuite/g++.dg/lto/odr-1_0.C
index 6fff88844c302f24e670661a72614b163c511641..318a047cb70f19b25af389b4306cd6d229e16bc4 100644
--- a/gcc/testsuite/g++.dg/lto/odr-1_0.C
+++ b/gcc/testsuite/g++.dg/lto/odr-1_0.C
@@ -1,8 +1,10 @@
 // PR c++/82414
 // { dg-lto-do link }
 enum vals {aa,cc}; // { dg-lto-warning "6: type 'vals' violates the C\\+\\+ One Definition Rule" }
+// { dg-lto-note "name 'cc' differs from name 'bb' defined in another translation unit" "" { target *-*-* } .-1 }
 struct a { // { dg-lto-warning "8: type 'struct a' violates the C\\+\\+ One Definition Rule" }
-  struct b *ptr; // { dg-lto-message "13: the first difference of corresponding definitions is field 'ptr'" }
+  struct b *ptr; // { dg-lto-note "13: the first difference of corresponding definitions is field 'ptr'" }
+  // { dg-lto-note "the incompatible type defined in another translation unit" "" { target *-*-* } .-1 }
   enum vals vals;
 };
 void test(struct a *a)
diff --git a/gcc/testsuite/g++.dg/lto/odr-1_1.C b/gcc/testsuite/g++.dg/lto/odr-1_1.C
index 494436a46c6547e1d23128bbdb04e0a067752c9a..a57bb3898aaf2009feeae0ae84ef78d8089c2b9e 100644
--- a/gcc/testsuite/g++.dg/lto/odr-1_1.C
+++ b/gcc/testsuite/g++.dg/lto/odr-1_1.C
@@ -1,9 +1,10 @@
 namespace {
-  struct b; // { dg-lto-message "type 'struct b' defined in anonymous namespace cannot match across the translation unit boundary" }
+  struct b; // { dg-lto-note "type 'struct b' defined in anonymous namespace cannot match across the translation unit boundary" }
  }
-enum vals {aa,bb,cc}; // { dg-lto-message "an enum with different value name is defined in another translation unit" }
-struct a { // { dg-lto-message "a different type is defined in another translation unit" }
-  struct b *ptr; // { dg-lto-message "a field of same name but different type is defined in another translation unit" }
+enum vals {aa,bb,cc}; // { dg-lto-note "an enum with different value name is defined in another translation unit" }
+// { dg-lto-note "mismatching definition" "" { target *-*-* } .-1 }
+struct a { // { dg-lto-note "a different type is defined in another translation unit" }
+  struct b *ptr; // { dg-lto-note "a field of same name but different type is defined in another translation unit" }
   enum vals vals;
 } a;
 void test(struct a *);
diff --git a/gcc/testsuite/g++.dg/lto/odr-2_1.C b/gcc/testsuite/g++.dg/lto/odr-2_1.C
index f384ae893b79e9a9aeb8225cddbd6573c061dda9..23cfccc241b77bf85b61dd3f4c62d9ca03b4bc6b 100644
--- a/gcc/testsuite/g++.dg/lto/odr-2_1.C
+++ b/gcc/testsuite/g++.dg/lto/odr-2_1.C
@@ -1,4 +1,4 @@
-class a { // { dg-lto-message "a different type is defined in another translation unit" }
+class a { // { dg-lto-note "a different type is defined in another translation unit" }
   int *b() const;
 };
 int *a::b() const { return 0; }
diff --git a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c
index 23a3b39fbb321501e703759543f9b6a98106bc97..bcdf7f076715a4b7af59af6b1e469cd8a5ea1779 100644
--- a/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c
+++ b/gcc/testsuite/gcc.dg/vect/nodump-vect-opt-info-2.c
@@ -3,7 +3,9 @@
 
 extern void accumulate (int x, int *a);
 
-int test_missing_function_defn (int *arr, int n) /* { dg-message "vectorized 0 loops in function" } */
+int test_missing_function_defn (int *arr, int n) /* { dg-note "5: vectorized 0 loops in function" } */
+/* { dg-prune-output "note: " } as we're not interested in matching any further
+   notes.  */
 {
   int sum = 0;
   for (int i = 0; i < n; ++i) /* { dg-missed "21: couldn't vectorize loop" } */
diff --git a/gcc/testsuite/gfortran.dg/goacc/routine-external-level-of-parallelism-2.f b/gcc/testsuite/gfortran.dg/goacc/routine-external-level-of-parallelism-2.f
index 0e8dfb19e2b43f37671aae80e6121dd83736f4e5..04d507fef9a6ab29c39cf615c0b19dbca9c69030 100644
--- a/gcc/testsuite/gfortran.dg/goacc/routine-external-level-of-parallelism-2.f
+++ b/gcc/testsuite/gfortran.dg/goacc/routine-external-level-of-parallelism-2.f
@@ -22,6 +22,8 @@
 ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
          do j = 1, n
             call workerr (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
+! { dg-bogus "note: routine 'workerr' declared here" "TODO" { xfail { ! offloading_enabled } } .-1 }
+! { dg-bogus "note: routine 'workerr_' declared here" "TODO" { xfail offloading_enabled } .-2 }
          end do
       end do
 !$acc end parallel loop
@@ -30,9 +32,12 @@
 ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
       do i = 1, n
 !$acc loop gang ! { dg-message "optimized: assigned OpenACC gang loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
          do j = 1, n
             call gangr (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
+! { dg-bogus "note: routine 'gangr' declared here" "TODO" { xfail { ! offloading_enabled } } .-2 }
+! { dg-bogus "note: routine 'gangr_' declared here" "TODO" { xfail offloading_enabled } .-3 }
          end do
       end do
 !$acc end parallel loop
@@ -83,6 +88,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop gang ! { dg-message "optimized: assigned OpenACC gang loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          call gangr (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -90,6 +96,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop worker ! { dg-message "optimized: assigned OpenACC worker loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          call gangr (a, n) ! { dg-message "optimized: assigned OpenACC gang vector loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -97,6 +104,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop vector ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          call gangr (a, n) ! { dg-message "optimized: assigned OpenACC gang worker loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -126,6 +134,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop worker ! { dg-message "optimized: assigned OpenACC worker loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          call workerr (a, n) ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -133,6 +142,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop vector ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          call workerr (a, n) ! { dg-message "optimized: assigned OpenACC worker loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -152,6 +162,8 @@
 !$acc parallel loop ! { dg-message "optimized: assigned OpenACC gang worker loop parallelism" }
       do i = 1, n
          call vectorr (a, n) ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+! { dg-bogus "note: routine 'vectorr' declared here" "TODO" { xfail { ! offloading_enabled } } .-1 }
+! { dg-bogus "note: routine 'vectorr_' declared here" "TODO" { xfail offloading_enabled } .-2 }
       end do
 !$acc end parallel loop
 
@@ -168,6 +180,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop vector ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          call vectorr (a, n) ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -201,6 +214,8 @@
 ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
          do j = 1, n
             a(i) = workerf (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
+! { dg-bogus "note: routine 'workerf' declared here" "TODO" { xfail { ! offloading_enabled } } .-1 }
+! { dg-bogus "note: routine 'workerf_' declared here" "TODO" { xfail offloading_enabled } .-2 }
          end do
       end do
 !$acc end parallel loop
@@ -209,9 +224,12 @@
 ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
       do i = 1, n
 !$acc loop gang ! { dg-message "optimized: assigned OpenACC gang loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
          do j = 1, n
             a(i) = gangf (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
+! { dg-bogus "note: routine 'gangf' declared here" "TODO" { xfail { ! offloading_enabled } } .-2 }
+! { dg-bogus "note: routine 'gangf_' declared here" "TODO" { xfail offloading_enabled } .-3 }
          end do
       end do
 !$acc end parallel loop
@@ -262,6 +280,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop gang ! { dg-message "optimized: assigned OpenACC gang loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          a(i) = gangf (a, n) ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -269,6 +288,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop worker ! { dg-message "optimized: assigned OpenACC worker loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          a(i) = gangf (a, n) ! { dg-message "optimized: assigned OpenACC gang vector loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -276,6 +296,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop vector ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          a(i) = gangf (a, n) ! { dg-message "optimized: assigned OpenACC gang worker loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -305,6 +326,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop worker ! { dg-message "optimized: assigned OpenACC worker loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          a(i) = workerf (a, n) ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -312,6 +334,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop vector ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          a(i) = workerf (a, n) ! { dg-message "optimized: assigned OpenACC worker loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
@@ -331,6 +354,8 @@
 !$acc parallel loop ! { dg-message "optimized: assigned OpenACC gang worker loop parallelism" }
       do i = 1, n
          a(i) = vectorf (a, n) ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+! { dg-bogus "note: routine 'vectorf' declared here" "TODO" { xfail { ! offloading_enabled } } .-1 }
+! { dg-bogus "note: routine 'vectorf_' declared here" "TODO" { xfail offloading_enabled } .-2 }
       end do
 !$acc end parallel loop
 
@@ -347,6 +372,7 @@
 !$acc end parallel loop
 
 !$acc parallel loop vector ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+! { dg-note "containing loop here" "" { target *-*-* } .-1 }
       do i = 1, n
          a(i) = vectorf (a, n) ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index e48a184f99137e6c500976176494083a68ffb05f..fce0989cd9ce32b1a41055335a4622540e80d593 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -1012,6 +1012,8 @@ if { [info procs saved-dg-test] == [list] } {
 	    }
 	    unset save_linenr_varnames
 	}
+
+	initialize_prune_notes
     }
 
     proc dg-test { args } {
@@ -1245,6 +1247,36 @@ proc dg-missed { args } {
     process-message saved-dg-warning "missed:" "$args"
 }
 
+# Look for messages with 'note: ' prefixes.
+# In addition to standard compiler diagnostics ('DK_NOTE', 'inform' functions,
+# "for additional details on an error message"),
+# this also includes output from '-fopt-info' for 'MSG_NOTE':
+# a general optimization info.
+# By default, any *excess* notes are pruned, meaning their appearance doesn't
+# trigger *excess errors*.  However, if 'dg-note' is used at least once in a
+# testcase, they're not pruned and instead must *all* be handled explicitly.
+# Thus, if looking for just single instances of messages with 'note: ' prefixes
+# without caring for all of them, use 'dg-message "note: [...]"' instead of
+# 'dg-note', or use 'dg-note' together with 'dg-prune-output "note: "'.
+
+variable prune_notes
+
+proc initialize_prune_notes { } {
+    global prune_notes
+    set prune_notes 1
+}
+
+initialize_prune_notes
+
+proc dg-note { args } {
+    upvar dg-messages dg-messages
+
+    global prune_notes
+    set prune_notes 0
+
+    process-message saved-dg-warning "note:" "$args"
+}
+
 # Check the existence of a gdb in the path, and return true if there
 # is one.
 #
diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp
index 77919e8443bf893092d80d2ebca5df3b68f431da..d0e0dc60138f866cc1c28651f39be3721c783146 100644
--- a/gcc/testsuite/lib/lto.exp
+++ b/gcc/testsuite/lib/lto.exp
@@ -161,9 +161,13 @@ proc lto_prune_warns { text } {
 
     # Ignore missing jobserver for tests that do more than 1 LTRANS unit
     regsub -all "(^|\n)\[^\n\]*: warning: using serial compilation of \[^\n\]*" $text "" text
+    regsub -all "(^|\n)\[^\n\]*: note: see the \[^\n\]*'-flto' option documentation\[^\n\]* for more information" $text "" text
 
-    # Ignore informational notes.
-    regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text
+    global prune_notes
+    if { $prune_notes } {
+	# Ignore informational notes.
+	regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text
+    }
 
     verbose "lto_prune_warns: exit: $text" 2
 
@@ -390,8 +394,8 @@ proc lto-can-handle-directive { op } {
     # A list of directives to recognize, and a list of directives
     # to remap them to.
     # For example, "dg-lto-warning" is implemented by calling "dg-warning".
-    set directives { dg-lto-warning dg-lto-message }
-    set remapped_directives { dg-warning dg-message }
+    set directives { dg-lto-warning dg-lto-message dg-lto-note }
+    set remapped_directives { dg-warning dg-message dg-note }
 
     set idx [lsearch -exact $directives $cmd]
     if { $idx != -1 } {
@@ -597,7 +601,7 @@ proc lto-get-options { src } {
 #
 # SRC1 is the full pathname of the main file of the testcase.
 # SID identifies a test suite in the names of temporary files.
-proc lto-execute { src1 sid } {
+proc lto-execute-1 { src1 sid } {
     global srcdir tmpdir
     global lto_option_list
     global tool
@@ -811,6 +815,14 @@ proc lto-execute { src1 sid } {
     }
 }
 
+proc lto-execute { src1 sid } {
+    lto-execute-1 $src1 $sid
+
+    # LTO testing doesn't use 'dg-runtest'/'dg-test', and thus doesn't call
+    # 'cleanup-after-saved-dg-test', so we have to clean up manually.
+    initialize_prune_notes
+}
+
 # Call pass if object readelf is ok, otherwise fail.
 # example: /* { dg-final { object-readelf Tag_ABI_enum_size int} } */
 proc object-readelf { args } {
diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index 2809f88b16f519fd302a614dd5839e6d36dc97cd..91f165bec3805f8f9e7d47c7558954809ff6fd06 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -54,8 +54,11 @@ proc prune_gcc_output { text } {
     regsub -all "(^|\n)\[ \]+from \[^\n\]*" $text "" text
     regsub -all "(^|\n)(In|of) module( \[^\n \]*,)? imported at \[^\n\]*" $text "" text
 
-    # Ignore informational notes.
-    regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text
+    global prune_notes
+    if { $prune_notes } {
+	# Ignore informational notes.
+	regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text
+    }
 
     # Ignore harmless -fpic warnings.
     regsub -all "(^|\n)\[^\n\]*: warning: -f(pic|PIC) ignored for target\[^\n\]*" $text "" text
diff --git a/libstdc++-v3/testsuite/lib/prune.exp b/libstdc++-v3/testsuite/lib/prune.exp
index 45c77d210d71a810634a516bfe981600b802305a..fd4a0ac7f97bf2d90d6a3c4e947bee6577f1914e 100644
--- a/libstdc++-v3/testsuite/lib/prune.exp
+++ b/libstdc++-v3/testsuite/lib/prune.exp
@@ -52,6 +52,8 @@ proc libstdc++-dg-prune { system text } {
     regsub -all "(^|\n)\[ \t\]*from \[^\n\]*" $text "" text
 
     # Ignore informational notes.
+    #TODO As this isn't even using 'gcc-dg.exp', cannot consider its
+    # 'variable prune_notes' (for 'dg-note') here.
     regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text
 
     # Ignore errata warning from IA64 assembler.