Skip to content

Commit 91fc5ae

Browse files
committed
Use only safe identical code folding with BOLT
"Identical code folding" (ICF) is the feature of an optimizer to find that two functions have the same code and that they can therefore be deduplicated in the binary. While this is usually safe, it can cause observable behavior differences if the program relies on the fact that the two functions have different addresses. CPython relies on this in (at least) Objects/typeobject.c, which defines two functions wrap_binaryfunc() and wrap_binaryfunc_l() with the same implementation, and stores their addresses in the slotdefs array. If these two functions have the same address, update_one_slot() in that file will fill in slots it shouldn't, causing, for instances, classes defined in Python that inherit from some built-in types to misbehave. As of LLVM 20 (llvm/llvm-project#116275), BOLT has a "safe ICF" mode, where it looks to see if there are any uses of a function symbol outside function calls (e.g., relocations in data sections) and skips ICF on such functions. The intent is that this avoids observable behavior differences but still saves storage as much as possible. This version is about two months old at the time of writing. To support older LLVM versions, we have to turn off ICF entirely. This problem was previously noticed for Windows/MSVC in python#53093 (and again in python#24098), where the default behavior of PGO is to enable ICF (which they expand to "identical COMDAT folding") and we had to turn it off.
1 parent 2fd09b0 commit 91fc5ae

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

configure

Lines changed: 49 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: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2129,6 +2129,29 @@ if test "$Py_BOLT" = 'true' ; then
21292129
else
21302130
AC_MSG_ERROR([merge-fdata is required for a --enable-bolt build but could not be found.])
21312131
fi
2132+
2133+
py_bolt_icf_flag="-icf=safe"
2134+
AC_CACHE_CHECK(
2135+
[whether ${LLVM_BOLT} supports safe identical code folding],
2136+
[py_cv_bolt_icf_safe],
2137+
[
2138+
saved_cflags="$CFLAGS"
2139+
saved_ldflags="$LDFLAGS"
2140+
CFLAGS="$CFLAGS_NODIST"
2141+
LDFLAGS="$LDFLAGS_NODIST"
2142+
AC_LINK_IFELSE(
2143+
[AC_LANG_PROGRAM([[]], [[]])],
2144+
[py_cv_bolt_icf_safe=no
2145+
${LLVM_BOLT} -icf=safe -o conftest.bolt conftest$EXEEXT >&AS_MESSAGE_LOG_FD 2>&1 dnl
2146+
&& py_cv_bolt_icf_safe=yes],
2147+
[AC_MSG_FAILURE([could not compile empty test program])])
2148+
CFLAGS="$saved_cflags"
2149+
LDFLAGS="$saved_ldflags"
2150+
]
2151+
)
2152+
if test "$py_cv_bolt_icf_safe" = no; then
2153+
py_bolt_icf_flag=""
2154+
fi
21322155
fi
21332156

21342157
dnl Enable BOLT of libpython if built.
@@ -2184,7 +2207,7 @@ then
21842207
-reorder-blocks=ext-tsp
21852208
-reorder-functions=cdsort
21862209
-split-functions
2187-
-icf=1
2210+
${py_bolt_icf_flag}
21882211
-inline-all
21892212
-split-eh
21902213
-reorder-functions-use-hot-size

0 commit comments

Comments
 (0)