Skip to content

Commit 33effce

Browse files
committed
gh-101525: Check whether to skip functions with computed gotos during BOLT runs
With LLVM >= 21.1.0 BOLT can handle computed gotos in PIC compiled code. However depending on the combination of --with-lto, --enable-shared, --enable-optmizations and using packed rellocations on the linker build configs might still need to skip functions containing computed gotos.
1 parent ca1e86f commit 33effce

File tree

2 files changed

+192
-7
lines changed

2 files changed

+192
-7
lines changed

configure

Lines changed: 93 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

configure.ac

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,6 +2137,34 @@ if test "$Py_BOLT" = 'true' ; then
21372137
AC_MSG_ERROR([llvm-bolt is required for a --enable-bolt build but could not be found.])
21382138
fi
21392139

2140+
# Check for packed relocations (-Wl,-z,pack-relative-relocs) which use DT_RELR format.
2141+
# BOLT has issues analyzing these compact relocations.
2142+
AC_MSG_CHECKING([for packed relocations in LDFLAGS])
2143+
has_packed_relocs="no"
2144+
case "$LDFLAGS $LDFLAGS_NODIST" in
2145+
*-Wl,-z,pack-relative-relocs*)
2146+
has_packed_relocs="yes"
2147+
;;
2148+
esac
2149+
AC_MSG_RESULT([$has_packed_relocs])
2150+
2151+
# Check BOLT version to determine if we need to skip functions with computed gotos.
2152+
AC_MSG_CHECKING([llvm-bolt version])
2153+
llvm_bolt_version=$("${LLVM_BOLT}" --version 2>/dev/null | grep -oE '[[0-9]]+\.[[0-9]]+\.[[0-9]]+' | head -1)
2154+
AC_MSG_RESULT([${llvm_bolt_version}])
2155+
2156+
# Parse version
2157+
llvm_bolt_major=$(echo "${llvm_bolt_version}" | cut -d. -f1)
2158+
llvm_bolt_minor=$(echo "${llvm_bolt_version}" | cut -d. -f2)
2159+
2160+
bolt_need_skip_computed_goto="yes"
2161+
if test -n "${llvm_bolt_major}" && test "${llvm_bolt_major}" -ge 21; then
2162+
if test "${llvm_bolt_major}" -gt 21 || test "${llvm_bolt_minor}" -ge 1; then
2163+
bolt_need_skip_computed_goto="no"
2164+
AC_MSG_RESULT([LLVM ${llvm_bolt_version} supports computed gotos])
2165+
fi
2166+
fi
2167+
21402168
AC_SUBST([MERGE_FDATA])
21412169
AC_PATH_TOOL([MERGE_FDATA], [merge-fdata], [''], [${llvm_path}])
21422170
if test -n "${MERGE_FDATA}" -a -x "${MERGE_FDATA}"
@@ -2166,15 +2194,80 @@ then
21662194
[BOLT_COMMON_FLAGS],
21672195
[m4_normalize("
21682196
[-update-debug-sections]
2169-
2170-
dnl At least LLVM 19.x doesn't support computed gotos in PIC compiled code.
2171-
dnl Exclude functions containing computed gotos.
2172-
dnl TODO this may be fixed in LLVM 20.x via https://github.com/llvm/llvm-project/pull/120267.
2173-
dnl GCC's LTO creates .lto_priv.0 clones of these functions.
2174-
[-skip-funcs=_PyEval_EvalFrameDefault,sre_ucs1_match/1,sre_ucs2_match/1,sre_ucs4_match/1,sre_ucs1_match.lto_priv.0/1,sre_ucs2_match.lto_priv.0/1,sre_ucs4_match.lto_priv.0/1]
21752197
")]
21762198
)
2199+
2200+
dnl BOLT versions before LLVM 21.1.0 don't support computed gotos in PIC compiled code.
2201+
dnl Exclude functions containing computed gotos for older versions.
2202+
dnl Fixed in LLVM 21.1.0+ via https://github.com/llvm/llvm-project/pull/120267
2203+
if test "${bolt_need_skip_computed_goto}" = "yes"; then
2204+
dnl Skip base computed goto functions
2205+
BOLT_COMMON_FLAGS="${BOLT_COMMON_FLAGS} -skip-funcs=_PyEval_EvalFrameDefault,sre_ucs1_match/1,sre_ucs2_match/1,sre_ucs4_match/1"
2206+
dnl GCC's LTO creates .lto_priv.0 clones that also need to be skipped
2207+
dnl Skip if packed relocs not present
2208+
if test "${has_packed_relocs}" != "yes" && test "${ac_cv_cc_name}" = "gcc" && test "${with_lto}" != "no" && test -n "${with_lto}"; then
2209+
BOLT_COMMON_FLAGS="${BOLT_COMMON_FLAGS},sre_ucs1_match.lto_priv.0/1,sre_ucs2_match.lto_priv.0/1,sre_ucs4_match.lto_priv.0/1"
2210+
fi
2211+
fi
2212+
2213+
dnl When packed relocations are used, BOLT cannot properly
2214+
dnl analyze the DT_RELR format. Build skip list for functions that fail with packed relocs.
2215+
if test "${has_packed_relocs}" = "yes"; then
2216+
bolt_base="_PyEval_EvalFrameDefault,sre_ucs1_match/1,sre_ucs2_match/1,sre_ucs4_match/1"
2217+
bolt_sre_lto="sre_ucs1_match.lto_priv.0/1,sre_ucs2_match.lto_priv.0/1,sre_ucs4_match.lto_priv.0/1"
2218+
bolt_all_lto="_PyEval_EvalFrameDefault.lto_priv.0/1,${bolt_sre_lto}"
2219+
2220+
case "${ac_cv_cc_name}" in
2221+
gcc)
2222+
dnl GCC's LTO creates .lto_priv.0 variants; PGO creates .localalias variants (in shared builds)
2223+
bolt_skip_list=""
2224+
2225+
dnl Determine what to include based on build configuration
2226+
bolt_need_base=$( (test "${bolt_need_skip_computed_goto}" != "yes" && test "${enable_shared}" = "yes") && echo "yes" || echo "no")
2227+
bolt_need_lto=$( (test "${with_lto}" != "no" && test -n "${with_lto}") && echo "yes" || echo "no")
2228+
bolt_need_pgo=$( (test "${enable_optimizations}" = "yes" && test "${enable_shared}" = "yes") && echo "yes" || echo "no")
2229+
2230+
dnl Build the skip list
2231+
test "${bolt_need_base}" = "yes" && bolt_skip_list="${bolt_base}"
2232+
if test "${bolt_need_lto}" = "yes"; then
2233+
if test "${enable_shared}" = "yes"; then
2234+
test -n "${bolt_skip_list}" && bolt_skip_list="${bolt_skip_list},"
2235+
bolt_skip_list="${bolt_skip_list}${bolt_all_lto}"
2236+
elif test "${bolt_need_skip_computed_goto}" != "yes"; then
2237+
bolt_skip_list="${bolt_all_lto}"
2238+
else
2239+
dnl BOLT < 21.1.0 + static: need to add LTO variants
2240+
test -n "${bolt_skip_list}" && bolt_skip_list="${bolt_skip_list},"
2241+
bolt_skip_list="${bolt_skip_list}${bolt_all_lto}"
2242+
fi
2243+
fi
2244+
if test "${bolt_need_pgo}" = "yes"; then
2245+
test -n "${bolt_skip_list}" && bolt_skip_list="${bolt_skip_list},"
2246+
if test "${bolt_need_lto}" = "yes"; then
2247+
bolt_skip_list="${bolt_skip_list}_PyEval_EvalFrameDefault.localalias.lto_priv.0/1"
2248+
else
2249+
bolt_skip_list="${bolt_skip_list}_PyEval_EvalFrameDefault.localalias/1"
2250+
fi
2251+
fi
2252+
2253+
dnl Apply the skip list
2254+
if test -n "${bolt_skip_list}"; then
2255+
if test "${bolt_need_skip_computed_goto}" = "yes"; then
2256+
BOLT_COMMON_FLAGS="${BOLT_COMMON_FLAGS},${bolt_skip_list}"
2257+
else
2258+
BOLT_COMMON_FLAGS="${BOLT_COMMON_FLAGS} -skip-funcs=${bolt_skip_list}"
2259+
fi
2260+
fi
2261+
;;
2262+
clang*)
2263+
if test "${bolt_need_skip_computed_goto}" != "yes"; then
2264+
BOLT_COMMON_FLAGS="${BOLT_COMMON_FLAGS} -skip-funcs=${bolt_base}"
2265+
fi
2266+
;;
2267+
esac
2268+
fi
21772269
fi
2270+
AC_MSG_RESULT([$BOLT_COMMON_FLAGS])
21782271

21792272
AC_ARG_VAR(
21802273
[BOLT_INSTRUMENT_FLAGS],

0 commit comments

Comments
 (0)