Skip to content

Commit 38b9903

Browse files
gburgessivChromeos LUCI
authored andcommitted
pgo_tools: update llvm pgo generation
- use `workon_llvm.sh` instead of hand-installing things - fix cross-* installation installation logic to install all cross-compilers, rather than trying to install (a potentially incorrect set of) binpkgs for some BUG=b:408157467 TEST=create_chroot_and_generate_pgo_profile passes with a bootstrap TEST=SDK update (crrev.com/c/6430206) Change-Id: I0f1775a03633d919b9a6256df167f044caa732ae Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/6430096 Reviewed-by: Bob Haarman <[email protected]> Commit-Queue: George Burgess <[email protected]> Tested-by: George Burgess <[email protected]>
1 parent 8d1da69 commit 38b9903

File tree

3 files changed

+33
-86
lines changed

3 files changed

+33
-86
lines changed

pgo_tools/create_chroot_and_generate_pgo_profile.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,23 @@ def generate_pgo_profile(
9999
else:
100100
git_utils.checkout(git_dir=llvm_project, ref=sha)
101101

102+
logging.info("Working on all toolchain projects")
103+
workon_llvm = (
104+
cros_paths.CHROOT_SOURCE_ROOT
105+
/ cros_paths.TOOLCHAIN_UTILS
106+
/ "llvm_tools"
107+
/ "workon_llvm.sh"
108+
)
102109
pgo_utils.run(
103110
cros_sdk
104111
+ [
105-
"cros-workon",
106-
"--host",
107-
"start",
108-
"sys-devel/llvm",
112+
workon_llvm,
113+
# No need to set any boards up here.
114+
"-",
109115
],
110116
cwd=repo_root,
111117
)
118+
logging.info("Running PGO profile generation script inside of the chroot")
112119
generate_pgo_profile_path = (
113120
cros_paths.CHROOT_SOURCE_ROOT
114121
/ cros_paths.TOOLCHAIN_UTILS_PYBIN

pgo_tools/generate_pgo_profile.py

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import sys
2727
import tempfile
2828
import textwrap
29-
from typing import Dict, FrozenSet, Generator, List, Optional
29+
from typing import Dict, Generator, List, Optional
3030

3131
from pgo_tools import pgo_utils
3232

@@ -132,34 +132,17 @@ def restore_llvm_binpkg() -> None:
132132
pgo_utils.run(pgo_utils.generate_quickpkg_restoration_command(pkg))
133133

134134

135-
def find_missing_cross_libs() -> FrozenSet[str]:
136-
"""Returns cross-* libraries that need to be installed for workloads."""
137-
equery_result = pgo_utils.run(
138-
["equery", "l", "--format=$cp", "cross-*/*"],
139-
check=False,
140-
stdout=subprocess.PIPE,
141-
)
142-
143-
# If no matching package is found, equery will exit with code 3.
144-
if equery_result.returncode == 3:
145-
return ALL_NEEDED_CROSS_LIBS
146-
147-
equery_result.check_returncode()
148-
has_packages = {x.strip() for x in equery_result.stdout.splitlines()}
149-
return ALL_NEEDED_CROSS_LIBS - has_packages
150-
151-
152-
def ensure_cross_libs_are_installed():
153-
"""Ensures that we have cross-* libs for all `IMPORTANT_TRIPLES`."""
154-
missing_packages = find_missing_cross_libs()
155-
if not missing_packages:
156-
logging.info("All cross-compiler libraries are already installed")
157-
return
158-
159-
missing_packages = sorted(missing_packages)
160-
logging.info("Installing cross-compiler libs: %s", missing_packages)
135+
def ensure_toolchain_is_up_to_date():
136+
"""Ensures that all toolchain/cross-compiler packages are up-to-date."""
137+
logging.info("Updating all toolchain packages to the new toolchain")
138+
# Using the command from go/crostc-mage-misc#using-the-new-toolchain
161139
pgo_utils.run(
162-
["sudo", "emerge", "-j", "-G"] + missing_packages,
140+
[
141+
"sudo",
142+
"cros_setup_toolchains",
143+
"--include-boards=amd64-generic",
144+
"--nousepkg",
145+
],
163146
)
164147

165148

@@ -501,19 +484,21 @@ def main(argv: List[str]):
501484
)
502485
)
503486

504-
logging.info("Ensuring `cross-` libraries are installed")
505-
ensure_cross_libs_are_installed()
487+
logging.info("Installing the new toolchain...")
488+
ensure_toolchain_is_up_to_date()
506489
tempdir = Path(tempfile.mkdtemp(prefix="generate_llvm_pgo_profile_"))
507490
try:
508491
workloads_path = tempdir / "workloads"
509492
logging.info("Fetching workloads")
510493
fetch_workloads_into(workloads_path)
511494

512-
# If our binpkg is not fresh, we may be operating with a weird LLVM
513-
# (e.g., a PGO'ed one ;) ). Ensure we always start with that binpkg as
514-
# our baseline.
515-
if not llvm_binpkg_is_fresh:
516-
restore_llvm_binpkg()
495+
# Subtle: ensure we always start with the initial LLVM. The new one
496+
# might emit a PGO profile version that the old one can't parse, which
497+
# makes it impossible to build the new with the old (w/ PGO enabled).
498+
#
499+
# The cross-compiler libs being out of sync is fine; `sys-devel/llvm`
500+
# ships with the cross-compiler libs it needs for host builds.
501+
restore_llvm_binpkg()
517502

518503
logging.info("Building PGO instrumented LLVM")
519504
emerge_pgo_generate_llvm()

pgo_tools/generate_pgo_profile_test.py

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,19 @@
1-
#!/usr/bin/env python3
21
# Copyright 2023 The ChromiumOS Authors
32
# Use of this source code is governed by a BSD-style license that can be
43
# found in the LICENSE file.
54

65
"""Tests for generate_pgo_profile."""
76

8-
from pathlib import Path
9-
import shutil
10-
import tempfile
11-
import unittest
127
from unittest import mock
138

9+
from llvm_tools import test_helpers
1410
from pgo_tools import generate_pgo_profile
1511
from pgo_tools import pgo_utils
1612

1713

18-
class Test(unittest.TestCase):
14+
class Test(test_helpers.TempDirTestCase):
1915
"""Tests for generate_pgo_profile."""
2016

21-
@mock.patch.object(pgo_utils, "run")
22-
def test_find_missing_cross_libs_works_for_empty_results(self, mock_run):
23-
mock_run.return_value.returncode = 3
24-
mock_run.return_value.stdout = ""
25-
self.assertEqual(
26-
generate_pgo_profile.find_missing_cross_libs(),
27-
generate_pgo_profile.ALL_NEEDED_CROSS_LIBS,
28-
)
29-
30-
mock_run.return_value.returncode = 0
31-
self.assertEqual(
32-
generate_pgo_profile.find_missing_cross_libs(),
33-
generate_pgo_profile.ALL_NEEDED_CROSS_LIBS,
34-
)
35-
36-
@mock.patch.object(pgo_utils, "run")
37-
def test_find_missing_cross_libs_filters_results_properly(self, mock_run):
38-
mock_run.return_value.returncode = 0
39-
mock_run.return_value.stdout = "\n".join(
40-
generate_pgo_profile.ALL_NEEDED_CROSS_LIBS
41-
)
42-
self.assertEqual(generate_pgo_profile.find_missing_cross_libs(), set())
43-
44-
some_cross_libs = sorted(generate_pgo_profile.ALL_NEEDED_CROSS_LIBS)
45-
del some_cross_libs[len(some_cross_libs) // 3 :]
46-
mock_run.return_value.stdout = "\n".join(
47-
some_cross_libs + ["cross-foo/bar"]
48-
)
49-
50-
expected_result = generate_pgo_profile.ALL_NEEDED_CROSS_LIBS - set(
51-
some_cross_libs
52-
)
53-
self.assertEqual(
54-
generate_pgo_profile.find_missing_cross_libs(), expected_result
55-
)
56-
57-
def make_tempdir(self) -> Path:
58-
tempdir = Path(tempfile.mkdtemp(prefix="generate_pgo_profile_test_"))
59-
self.addCleanup(lambda: shutil.rmtree(tempdir))
60-
return tempdir
61-
6217
def test_read_exactly_one_dirent_works(self):
6318
tempdir = self.make_tempdir()
6419
ent = tempdir / "one-ent"

0 commit comments

Comments
 (0)