Merge from 3.5 for issue #25188.
diff --git a/Lib/test/libregrtest/cmdline.py b/Lib/test/libregrtest/cmdline.py
index ae1aeb9..6b18b3a 100644
--- a/Lib/test/libregrtest/cmdline.py
+++ b/Lib/test/libregrtest/cmdline.py
@@ -236,6 +236,8 @@
     group.add_argument('--list-tests', action='store_true',
                        help="only write the name of tests that will be run, "
                             "don't execute them")
+    group.add_argument('-P', '--pgo', dest='pgo', action='store_true',
+                       help='enable Profile Guided Optimization training')
 
     parser.add_argument('args', nargs=argparse.REMAINDER,
                         help=argparse.SUPPRESS)
@@ -279,7 +281,7 @@
          findleaks=False, use_resources=None, trace=False, coverdir='coverage',
          runleaks=False, huntrleaks=False, verbose2=False, print_slow=False,
          random_seed=None, use_mp=None, verbose3=False, forever=False,
-         header=False, failfast=False, match_tests=None)
+         header=False, failfast=False, match_tests=None, pgo=False)
     for k, v in kwargs.items():
         if not hasattr(ns, k):
             raise TypeError('%r is an invalid keyword argument '
@@ -299,6 +301,8 @@
         parser.error("-l and -j don't go together!")
     if ns.failfast and not (ns.verbose or ns.verbose3):
         parser.error("-G/--failfast needs either -v or -W")
+    if ns.pgo and (ns.verbose or ns.verbose2 or ns.verbose3):
+        parser.error("--pgo/-v don't go together!")
 
     if ns.quiet:
         ns.verbose = 0
diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
index 30d8a59..aa95b21 100644
--- a/Lib/test/libregrtest/main.py
+++ b/Lib/test/libregrtest/main.py
@@ -103,7 +103,10 @@
     def display_progress(self, test_index, test):
         if self.ns.quiet:
             return
-        fmt = "[{1:{0}}{2}/{3}] {4}" if self.bad else "[{1:{0}}{2}] {4}"
+        if self.bad and not self.ns.pgo:
+            fmt = "[{1:{0}}{2}/{3}] {4}"
+        else:
+            fmt = "[{1:{0}}{2}] {4}"
         print(fmt.format(self.test_count_width, test_index,
                          self.test_count, len(self.bad), test),
               flush=True)
@@ -238,6 +241,11 @@
             print(count(len(omitted), "test"), "omitted:")
             printlist(omitted)
 
+        # If running the test suite for PGO then no one cares about
+        # results.
+        if self.ns.pgo:
+            return
+
         if self.good and not self.ns.quiet:
             if (not self.bad
                 and not self.skipped
@@ -314,7 +322,7 @@
         # For a partial run, we do not need to clutter the output.
         if (self.ns.verbose
             or self.ns.header
-            or not (self.ns.quiet or self.ns.single
+            or not (self.ns.pgo or self.ns.quiet or self.ns.single
                     or self.tests or self.ns.args)):
             # Print basic platform information
             print("==", platform.python_implementation(), *sys.version.split())
diff --git a/Lib/test/libregrtest/runtest.py b/Lib/test/libregrtest/runtest.py
index 4cc2588..043f23c 100644
--- a/Lib/test/libregrtest/runtest.py
+++ b/Lib/test/libregrtest/runtest.py
@@ -65,6 +65,7 @@
     timeout -- dump the traceback and exit if a test takes more than
                timeout seconds
     failfast, match_tests -- See regrtest command-line flags for these.
+    pgo -- if true, suppress any info irrelevant to a generating a PGO build
 
     Returns the tuple result, test_time, where result is one of the constants:
         INTERRUPTED      KeyboardInterrupt when run under -j
@@ -82,6 +83,7 @@
     failfast = ns.failfast
     match_tests = ns.match_tests
     timeout = ns.timeout
+    pgo = ns.pgo
 
     use_timeout = (timeout is not None)
     if use_timeout:
@@ -110,7 +112,7 @@
                 sys.stdout = stream
                 sys.stderr = stream
                 result = runtest_inner(test, verbose, quiet, huntrleaks,
-                                       display_failure=False)
+                                       display_failure=False, pgo=pgo)
                 if result[0] == FAILED:
                     output = stream.getvalue()
                     orig_stderr.write(output)
@@ -121,7 +123,7 @@
         else:
             support.verbose = verbose  # Tell tests to be moderately quiet
             result = runtest_inner(test, verbose, quiet, huntrleaks,
-                                   display_failure=not verbose)
+                                   display_failure=not verbose, pgo=pgo)
         return result
     finally:
         if use_timeout:
@@ -131,7 +133,7 @@
 
 
 def runtest_inner(test, verbose, quiet,
-                  huntrleaks=False, display_failure=True):
+                  huntrleaks=False, display_failure=True, *, pgo=False):
     support.unload(test)
 
     test_time = 0.0
@@ -142,7 +144,7 @@
         else:
             # Always import it from the test package
             abstest = 'test.' + test
-        with saved_test_environment(test, verbose, quiet) as environment:
+        with saved_test_environment(test, verbose, quiet, pgo=pgo) as environment:
             start_time = time.time()
             the_module = importlib.import_module(abstest)
             # If the test has a test_main, that will run the appropriate
@@ -162,24 +164,28 @@
                 refleak = dash_R(the_module, test, test_runner, huntrleaks)
             test_time = time.time() - start_time
     except support.ResourceDenied as msg:
-        if not quiet:
+        if not quiet and not pgo:
             print(test, "skipped --", msg, flush=True)
         return RESOURCE_DENIED, test_time
     except unittest.SkipTest as msg:
-        if not quiet:
+        if not quiet and not pgo:
             print(test, "skipped --", msg, flush=True)
         return SKIPPED, test_time
     except KeyboardInterrupt:
         raise
     except support.TestFailed as msg:
-        if display_failure:
-            print("test", test, "failed --", msg, file=sys.stderr, flush=True)
-        else:
-            print("test", test, "failed", file=sys.stderr, flush=True)
+        if not pgo:
+            if display_failure:
+                print("test", test, "failed --", msg, file=sys.stderr,
+                      flush=True)
+            else:
+                print("test", test, "failed", file=sys.stderr, flush=True)
         return FAILED, test_time
     except:
         msg = traceback.format_exc()
-        print("test", test, "crashed --", msg, file=sys.stderr, flush=True)
+        if not pgo:
+            print("test", test, "crashed --", msg, file=sys.stderr,
+                  flush=True)
         return FAILED, test_time
     else:
         if refleak:
diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py
index a732d70..4473db4 100644
--- a/Lib/test/libregrtest/runtest_mp.py
+++ b/Lib/test/libregrtest/runtest_mp.py
@@ -42,6 +42,8 @@
            '-X', 'faulthandler',
            '-m', 'test.regrtest',
            '--slaveargs', slaveargs]
+    if ns.pgo:
+        cmd += ['--pgo']
 
     # Running the child from the same working directory as regrtest's original
     # invocation ensures that TEMPDIR for the child is the same when
@@ -175,7 +177,7 @@
                 item = output.get(timeout=timeout)
             except queue.Empty:
                 running = get_running(workers)
-                if running:
+                if running and not regrtest.ns.pgo:
                     print('running: %s' % ', '.join(running))
                 continue
 
@@ -189,17 +191,18 @@
             text = test
             ok, test_time = result
             if (ok not in (CHILD_ERROR, INTERRUPTED)
-                and test_time >= PROGRESS_MIN_TIME):
+                and test_time >= PROGRESS_MIN_TIME
+                and not regrtest.ns.pgo):
                 text += ' (%.0f sec)' % test_time
             running = get_running(workers)
-            if running:
+            if running and not regrtest.ns.pgo:
                 text += ' -- running: %s' % ', '.join(running)
             regrtest.display_progress(test_index, text)
 
             # Copy stdout and stderr from the child process
             if stdout:
                 print(stdout, flush=True)
-            if stderr:
+            if stderr and not regrtest.ns.pgo:
                 print(stderr, file=sys.stderr, flush=True)
 
             if result[0] == INTERRUPTED:
diff --git a/Lib/test/libregrtest/save_env.py b/Lib/test/libregrtest/save_env.py
index 4f6a1aa..90900a9 100644
--- a/Lib/test/libregrtest/save_env.py
+++ b/Lib/test/libregrtest/save_env.py
@@ -41,10 +41,11 @@
 
     changed = False
 
-    def __init__(self, testname, verbose=0, quiet=False):
+    def __init__(self, testname, verbose=0, quiet=False, *, pgo=False):
         self.testname = testname
         self.verbose = verbose
         self.quiet = quiet
+        self.pgo = pgo
 
     # To add things to save and restore, add a name XXX to the resources list
     # and add corresponding get_XXX/restore_XXX functions.  get_XXX should
@@ -273,7 +274,7 @@
             if current != original:
                 self.changed = True
                 restore(original)
-                if not self.quiet:
+                if not self.quiet and not self.pgo:
                     print("Warning -- {} was modified by {}".format(
                                                  name, self.testname),
                                                  file=sys.stderr)