Skip to content

Commit ff9b31f

Browse files
committed
Add additional patch folder for performance patches
This adds a second llvm-project patch directory, intended for performance enhancement patches which can be kept optional to avoid blocking builds if they become out of date with the main branch. A new CMake option controls whether or not to apply the patches, and a new script is included to manage the patching process to make it easier to identify when there is a problem with a patch.
1 parent de4eb46 commit ff9b31f

File tree

3 files changed

+165
-13
lines changed

3 files changed

+165
-13
lines changed

CMakeLists.txt

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ option(
134134
the tools every time you update llvm-project."
135135
ON
136136
)
137+
option(
138+
APPLY_LLVM_PERFORMANCE_PATCHES
139+
"During checkout, apply optional downstream patches to
140+
llvm-project to improve performance."
141+
)
137142
set(
138143
FVP_INSTALL_DIR
139144
"${CMAKE_CURRENT_SOURCE_DIR}/fvp/install" CACHE STRING
@@ -280,24 +285,17 @@ if(NOT (LLVM_TOOLCHAIN_C_LIBRARY STREQUAL llvmlibc)) # libc in a separate repo?
280285
read_repo_version(${LLVM_TOOLCHAIN_C_LIBRARY} ${LLVM_TOOLCHAIN_C_LIBRARY})
281286
endif()
282287

283-
# The patches are generated from custom branch, with followin command:
284-
# git format-patch -k origin/main
285-
# The patches apply cleanly against llvm-project commit
286-
# ed551e0778a35f00ab60f1c80d83ea8274d8d400.
287-
set(
288-
llvm_project_patches
289-
${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm-project/0001-libc-tests-with-picolibc-xfail-one-remaining-test.patch
290-
${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm-project/0002-libc-tests-with-picolibc-disable-large-tests.patch
291-
${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm-project/0003-Disable-failing-compiler-rt-test.patch
292-
${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm-project/0004-libc-tests-with-picolibc-XFAIL-uses-of-atomics.patch
293-
${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm-project/0005-libc-tests-with-picolibc-mark-two-more-large-tests.patch
294-
)
288+
set(LLVM_PATCH_COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/patch_llvm.py ${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm-project)
289+
if (APPLY_LLVM_PERFORMANCE_PATCHES)
290+
set(LLVM_PATCH_COMMAND ${LLVM_PATCH_COMMAND} && ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/patch_llvm.py ${CMAKE_CURRENT_SOURCE_DIR}/patches/llvm-project-perf)
291+
endif()
292+
295293
FetchContent_Declare(llvmproject
296294
GIT_REPOSITORY https://github.com/llvm/llvm-project.git
297295
GIT_TAG "${llvmproject_TAG}"
298296
GIT_SHALLOW "${llvmproject_SHALLOW}"
299297
GIT_PROGRESS TRUE
300-
PATCH_COMMAND git reset --quiet --hard && git clean --quiet --force -dx && git am -k --ignore-whitespace --3way ${llvm_project_patches}
298+
PATCH_COMMAND ${LLVM_PATCH_COMMAND}
301299
# Add the llvm subdirectory later to ensure that
302300
# LLVMEmbeddedToolchainForArm is the first project declared.
303301
# Otherwise CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT

cmake/patch_llvm.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Script to apply a set of patches to llvm-project sources.
5+
"""
6+
7+
import argparse
8+
import os
9+
import subprocess
10+
import sys
11+
12+
13+
def main():
14+
parser = argparse.ArgumentParser(description=__doc__)
15+
parser.add_argument(
16+
"patchdir",
17+
help="Set of patches to apply. This should be a directory containing one or more ordered *.patch files.",
18+
)
19+
parser.add_argument(
20+
"--llvm_dir",
21+
help="Directory of the llvm-project git checkout, if not the current directory.",
22+
)
23+
parser.add_argument(
24+
"--method",
25+
choices=["am", "apply"],
26+
default="apply",
27+
help="Git command to use. git am will add each patch as a commit, whereas git apply will leave patched changes staged.",
28+
)
29+
parser.add_argument(
30+
"--reset",
31+
help="Clean and reset the repo to a specified commit before patching.",
32+
)
33+
parser.add_argument(
34+
"--restore_on_fail",
35+
action="store_true",
36+
help="If a patch in a series cannot be applied, restore the original state instead of leaving patches missing. Return code will be 2 instead of 1.",
37+
)
38+
args = parser.parse_args()
39+
40+
if args.reset:
41+
reset_args = ["git", "reset", "--quiet", "--hard"]
42+
subprocess.check_output(reset_args, cwd=args.llvm_dir)
43+
clean_args = ["git", "clean", "--quiet", "--force", "-dx"]
44+
subprocess.check_output(clean_args, cwd=args.llvm_dir)
45+
46+
patch_names = []
47+
for patch_name in os.listdir(args.patchdir):
48+
if patch_name.endswith(".patch"):
49+
patch_names.append(patch_name)
50+
patch_names.sort()
51+
52+
print(f"Found {len(patch_names)} patches to apply:")
53+
for patch_name in patch_names:
54+
print(patch_name)
55+
56+
if args.method == "am":
57+
merge_args = ["git", "am", "-k", "--ignore-whitespace", "--3way"]
58+
for patch_name in patch_names:
59+
merge_args.append(os.path.join(args.patchdir, patch_name))
60+
p = subprocess.run(
61+
merge_args, cwd=args.llvm_dir, capture_output=True, text=True
62+
)
63+
print(p.stdout)
64+
print(p.stderr)
65+
66+
if p.returncode == 0:
67+
print(f"All patches applied.")
68+
sys.exit(0)
69+
if args.restore_on_fail:
70+
# Check that the operation can be aborted.
71+
if (
72+
'To restore the original branch and stop patching, run "git am --abort".'
73+
in p.stdout
74+
):
75+
print("Aborting git am...")
76+
subprocess.run(["git", "am", "--abort"], cwd=args.llvm_dir, check=True)
77+
sys.exit(2)
78+
sys.exit(1)
79+
else:
80+
applied_patches = []
81+
for patch_name in patch_names:
82+
patch_file = os.path.join(args.patchdir, patch_name)
83+
print(f"Checking {patch_file}...")
84+
# Check that the patch applies before trying to apply it.
85+
apply_check_args = [
86+
"git",
87+
"apply",
88+
"--ignore-whitespace",
89+
"--3way",
90+
"--check",
91+
patch_file,
92+
]
93+
p_check = subprocess.run(apply_check_args, cwd=args.llvm_dir)
94+
95+
if p_check.returncode == 0:
96+
# Patch will apply.
97+
print(f"Applying {patch_file}...")
98+
apply_args = [
99+
"git",
100+
"apply",
101+
"--ignore-whitespace",
102+
"--3way",
103+
patch_file,
104+
]
105+
apply_args = subprocess.run(apply_args, cwd=args.llvm_dir, check=True)
106+
applied_patches.append(patch_file)
107+
else:
108+
# Patch won't apply.
109+
print(f"Unable to apply {patch_file}")
110+
if args.restore_on_fail:
111+
# Remove any patches that have already been applied.
112+
while len(applied_patches) > 0:
113+
r_patch = applied_patches.pop()
114+
print(f"Reversing {r_patch}...")
115+
reverse_args = [
116+
"git",
117+
"apply",
118+
"--ignore-whitespace",
119+
"--3way",
120+
"--reverse",
121+
r_patch,
122+
]
123+
p_check = subprocess.run(
124+
reverse_args, cwd=args.llvm_dir, check=True
125+
)
126+
print(f"Rollback successful, failure occured on {patch_file}")
127+
sys.exit(2)
128+
sys.exit(1)
129+
print(f"All patches applied.")
130+
131+
132+
main()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
From e79697a54cba9bfc1a755ed048e42054d679de61 Mon Sep 17 00:00:00 2001
2+
From: David Candler <[email protected]>
3+
Date: Wed, 2 Oct 2024 14:13:31 +0100
4+
Subject: [PATCH] Placeholder commit
5+
6+
---
7+
.gitignore | 2 +-
8+
1 file changed, 1 insertion(+), 1 deletion(-)
9+
10+
diff --git a/.gitignore b/.gitignore
11+
index 0e7c6c790013..dfa0b8da0ccd 100644
12+
--- a/.gitignore
13+
+++ b/.gitignore
14+
@@ -1,4 +1,4 @@
15+
-#==============================================================================#
16+
+#==============================================================================#
17+
# This file specifies intentionally untracked files that git should ignore.
18+
# See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html
19+
#
20+
--
21+
2.34.1
22+

0 commit comments

Comments
 (0)