Skip to content

Commit 7803d04

Browse files
authored
Add additional patch folder for performance patches (#518)
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 b9efd0b commit 7803d04

File tree

4 files changed

+176
-13
lines changed

4 files changed

+176
-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-
# 327124ece7d59de56ca0f9faa2cd82af68c011b9.
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: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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 pathlib
10+
import subprocess
11+
import sys
12+
13+
14+
def main():
15+
parser = argparse.ArgumentParser(description=__doc__)
16+
parser.add_argument(
17+
"patchdir",
18+
help="Set of patches to apply. This should be a directory containing one or more ordered *.patch files.",
19+
)
20+
parser.add_argument(
21+
"--llvm_dir",
22+
help="Directory of the llvm-project git checkout, if not the current directory.",
23+
)
24+
parser.add_argument(
25+
"--method",
26+
choices=["am", "apply"],
27+
default="apply",
28+
help="Git command to use. git am will add each patch as a commit, whereas git apply will leave patched changes staged.",
29+
)
30+
parser.add_argument(
31+
"--reset",
32+
help="Clean and hard reset the repo to a specified commit before patching.",
33+
)
34+
parser.add_argument(
35+
"--restore_on_fail",
36+
action="store_true",
37+
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.",
38+
)
39+
args = parser.parse_args()
40+
41+
if args.llvm_dir:
42+
git_cmd = ["git", "-C", args.llvm_dir]
43+
else:
44+
git_cmd = ["git"]
45+
46+
if args.reset:
47+
reset_args = git_cmd + ["reset", "--quiet", "--hard", args.reset]
48+
subprocess.check_output(reset_args)
49+
clean_args = git_cmd + ["clean", "--quiet", "--force", "-dx", args.reset]
50+
subprocess.check_output(clean_args)
51+
52+
abs_patch_dir = os.path.abspath(args.patchdir)
53+
patch_list = list(pathlib.Path(abs_patch_dir).glob("*.patch"))
54+
patch_list.sort()
55+
56+
print(f"Found {len(patch_list)} patches to apply:")
57+
print("\n".join(p.name for p in patch_list))
58+
59+
if args.method == "am":
60+
merge_args = git_cmd + ["am", "-k", "--ignore-whitespace", "--3way"]
61+
for patch in patch_list:
62+
merge_args.append(str(patch))
63+
p = subprocess.run(merge_args, capture_output=True, text=True)
64+
print(p.stdout)
65+
print(p.stderr)
66+
67+
if p.returncode == 0:
68+
print(f"All patches applied.")
69+
sys.exit(0)
70+
if args.restore_on_fail:
71+
# Check that the operation can be aborted.
72+
# git am doesn't give any specific return codes,
73+
# so check for unresolved working files.
74+
rebase_apply_path = os.path.join(".git", "rebase-apply")
75+
if args.llvm_dir:
76+
rebase_apply_path = os.path.join(args.llvm_dir, rebase_apply_path)
77+
if os.path.isdir(rebase_apply_path):
78+
print("Aborting git am...")
79+
subprocess.run(git_cmd + ["am", "--abort"], check=True)
80+
print(f"Abort successful.")
81+
sys.exit(2)
82+
else:
83+
print("Unable to abort.")
84+
sys.exit(1)
85+
else:
86+
applied_patches = []
87+
for current_patch in patch_list:
88+
print(f"Checking {current_patch.name}...")
89+
# Check that the patch applies before trying to apply it.
90+
apply_check_args = git_cmd + [
91+
"apply",
92+
"--ignore-whitespace",
93+
"--3way",
94+
"--check",
95+
str(current_patch),
96+
]
97+
p_check = subprocess.run(apply_check_args)
98+
99+
if p_check.returncode == 0:
100+
# Patch will apply.
101+
print(f"Applying {current_patch.name}...")
102+
apply_args = git_cmd + [
103+
"apply",
104+
"--ignore-whitespace",
105+
"--3way",
106+
str(current_patch),
107+
]
108+
apply_args = subprocess.run(apply_args, check=True)
109+
applied_patches.append(current_patch)
110+
else:
111+
# Patch won't apply.
112+
print(f"Unable to apply {current_patch.name}")
113+
if args.restore_on_fail:
114+
# Remove any patches that have already been applied.
115+
while len(applied_patches) > 0:
116+
previous_patch = applied_patches.pop()
117+
print(f"Reversing {previous_patch.name}...")
118+
reverse_args = git_cmd + [
119+
"apply",
120+
"--ignore-whitespace",
121+
"--3way",
122+
"--reverse",
123+
str(previous_patch),
124+
]
125+
p_check = subprocess.run(reverse_args, check=True)
126+
print(
127+
f"Rollback successful, failure occured on {current_patch.name}"
128+
)
129+
sys.exit(2)
130+
sys.exit(1)
131+
print(f"All patches applied.")
132+
133+
134+
main()

docs/building-from-source.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,12 @@ The same build directory can be used for both native and MinGW toolchains.
148148

149149
See [patches](https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/tree/main/patches)
150150
directory for the current set of differences from upstream.
151+
152+
The patches for llvm-project are split between two folders, llvm-project and
153+
llvm-project-perf. The former are generally required for building and
154+
successfully running all tests. The patches in llvm-project-perf are optional,
155+
and designed to improve performance in certain circumstances.
156+
157+
To reduce divergence from upstream and potential patch conflicts, the
158+
performance patches are not applied by default, but can be enabled for an
159+
automatic checkout with the APPLY_LLVM_PERFORMANCE_PATCHES option.
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)