Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 01 Jan 2025 23:24:19 +0000
From:      bugzilla-noreply@freebsd.org
To:        toolchain@FreeBSD.org
Subject:   [Bug 276170] LLVM bug prevents from enabling PGO optimization for Python 3.11+
Message-ID:  <bug-276170-29464-4xpH0CSFRB@https.bugs.freebsd.org/bugzilla/>
In-Reply-To: <bug-276170-29464@https.bugs.freebsd.org/bugzilla/>
References:  <bug-276170-29464@https.bugs.freebsd.org/bugzilla/>

next in thread | previous in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D276170

Dimitry Andric <dim@FreeBSD.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|New                         |In Progress
                 CC|                            |emaste@freebsd.org

--- Comment #44 from Dimitry Andric <dim@FreeBSD.org> ---
After some more investigation I found the cause, which is (again) the fact =
that
assertions are _disabled_ on stable and release branches.

This particular "error" is occurring in
contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp, on line 422:

   414    if (CodeGenOpts.hasProfileClangUse()) {
   415      auto ReaderOrErr =3D llvm::IndexedInstrProfReader::create(
   416          CodeGenOpts.ProfileInstrumentUsePath, *FS,
   417          CodeGenOpts.ProfileRemappingFile);
   418      // We're checking for profile read errors in CompilerInvocation=
, so
if
   419      // there was an error it should've already been caught. If it
hasn't been
   420      // somehow, trip an assertion.
   421      assert(ReaderOrErr);
   422      PGOReader =3D std::move(ReaderOrErr.get());
   423    }

llvm::IndexedInstrProfReader::create() returns a llvm::Expected<> instance,
which is similar to std::expected: it can contain either a "good" return va=
lue,
or an error.

In some llvm build configurations, when you attempt to use the return value
without checking whether it contains an error, you get "Expected<T> must be
checked before access or destruction". This occurs even if the Expected<>
object contains a valid value, in which case you get "Expected<T> value was=
 in
success state".

When llvm is built with assertions (WITH_LLVM_ASSERTIONS, which is on by
default on -CURRENT, but not on stable or release branches), the assert()
statement on line 421 is calling llvm::Expected<>::operator bool(), which
checks whether the contained object is valid, and if so it resets the check=
ed
state:

  /// Bool conversion. Returns true if this Error is in a failure state,
  /// and false if it is in an accept state. If the error is in a Success s=
tate
  /// it will be considered checked.
  explicit operator bool() {
    setChecked(getPtr() =3D=3D nullptr);
    return getPtr() !=3D nullptr;
  }

Then in line 422 the contained object is moved out of the 'ReaderOrErr'
variable, into the 'PGOReader' variable. Finally, the 'ReaderOrErr' variabl=
e,
which is now empty, is destroyed.

However, when llvm is built without assertions (WITHOUT_LLVM_ASSERTIONS), t=
he
assert() statement on line 421 does nothing, and the  'ReaderOrErr' variabl=
e is
unaffected. Then in line 422, llvm::Expected<>::get() is called:

  /// Returns a reference to the stored T value.
  reference get() {
    assertIsChecked();
    return *getStorage();
  }

The first thing get() does is looking if the Expected<> object was checked,=
 and
if not, it prints "Expected<T> must be checked before access or destruction"
and the whole program dies.

Finally, assertIsChecked() is only really doing something if the global llvm
macro LLVM_ENABLE_ABI_BREAKING_CHECKS is defined:

  void assertIsChecked() const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
    if (LLVM_UNLIKELY(Unchecked))
      fatalUncheckedExpected();
#endif
  }

In the upstream build system, LLVM_ENABLE_ABI_BREAKING_CHECKS is typically 0
when assertions are off, and 1 when assertions are on. In the FreeBSD case,
this use to always be defined as 1 in
lib/clang/include/llvm/Config/abi-breaking.h, until base 1c83996beda7 ("Adj=
ust
LLVM_ENABLE_ABI_BREAKING_CHECKS depending on NDEBUG"):

    15  /* Define to enable checks that alter the LLVM C++ ABI */
    16  #ifdef NDEBUG
    17  #define LLVM_ENABLE_ABI_BREAKING_CHECKS 0
    18  #else
    19  #define LLVM_ENABLE_ABI_BREAKING_CHECKS 1
    20  #endif

Unfortunately 14.2 does not have this commit, so the combination of
MK_LLVM_ASSERTIONS=3Dno and LLVM_ENABLE_ABI_BREAKING_CHECKS=3D1 leads to the
scenario describe above: the assert() statement in CodeGenModule.cpp line 4=
21
does nothing, but ReaderOrErr.get() still performs the check and aborts.

I merged base 1c83996beda7 to stable/14 in base 86de9cd1f1b5, and to stable=
/13
in base 44be5a00bedd, but this is unfortunately not available in 14.2-RELEA=
SE
or 13.4-RELEASE, so for those releases there isn't much I can do except to =
try
to roll it into a Erratum.

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-276170-29464-4xpH0CSFRB>