@@ -2137,6 +2137,34 @@ if test "$Py_BOLT" = 'true' ; then |
2137 | 2137 | AC_MSG_ERROR([llvm-bolt is required for a --enable-bolt build but could not be found.]) |
2138 | 2138 | fi |
2139 | 2139 |
|
| 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 | + |
2140 | 2168 | AC_SUBST([MERGE_FDATA]) |
2141 | 2169 | AC_PATH_TOOL([MERGE_FDATA], [merge-fdata], [''], [${llvm_path}]) |
2142 | 2170 | if test -n "${MERGE_FDATA}" -a -x "${MERGE_FDATA}" |
@@ -2166,15 +2194,80 @@ then |
2166 | 2194 | [BOLT_COMMON_FLAGS], |
2167 | 2195 | [m4_normalize(" |
2168 | 2196 | [-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] |
2175 | 2197 | ")] |
2176 | 2198 | ) |
| 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 |
2177 | 2269 | fi |
| 2270 | +AC_MSG_RESULT([$BOLT_COMMON_FLAGS]) |
2178 | 2271 |
|
2179 | 2272 | AC_ARG_VAR( |
2180 | 2273 | [BOLT_INSTRUMENT_FLAGS], |
|