diff options
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r-- | llvm/lib/Support/APFloat.cpp | 130 | ||||
-rw-r--r-- | llvm/lib/Support/BLAKE3/CMakeLists.txt | 3 | ||||
-rw-r--r-- | llvm/lib/Support/FileCollector.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Support/Unix/Path.inc | 2 | ||||
-rw-r--r-- | llvm/lib/Support/VirtualFileSystem.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Support/Windows/Threading.inc | 62 |
6 files changed, 199 insertions, 12 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 5e0b29f..46084c5 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -900,6 +900,30 @@ writeSignedDecimal (char *dst, int value) return dst; } +// Compute the ULP of the input using a definition from: +// Jean-Michel Muller. On the definition of ulp(x). [Research Report] RR-5504, +// LIP RR-2005-09, INRIA, LIP. 2005, pp.16. inria-00070503 +static APFloat harrisonUlp(const APFloat &X) { + const fltSemantics &Sem = X.getSemantics(); + switch (X.getCategory()) { + case APFloat::fcNaN: + return APFloat::getQNaN(Sem); + case APFloat::fcInfinity: + return APFloat::getInf(Sem); + case APFloat::fcZero: + return APFloat::getSmallest(Sem); + case APFloat::fcNormal: + break; + } + if (X.isDenormal() || X.isSmallestNormalized()) + return APFloat::getSmallest(Sem); + int Exp = ilogb(X); + if (X.getExactLog2() != INT_MIN) + Exp -= 1; + return scalbn(APFloat::getOne(Sem), Exp - (Sem.precision - 1), + APFloat::rmNearestTiesToEven); +} + namespace detail { /* Constructors. */ void IEEEFloat::initialize(const fltSemantics *ourSemantics) { @@ -5306,12 +5330,110 @@ Expected<APFloat::opStatus> DoubleAPFloat::convertFromString(StringRef S, return Ret; } +// The double-double lattice of values corresponds to numbers which obey: +// - abs(lo) <= 1/2 * ulp(hi) +// - roundTiesToEven(hi + lo) == hi +// +// nextUp must choose the smallest output > input that follows these rules. +// nexDown must choose the largest output < input that follows these rules. APFloat::opStatus DoubleAPFloat::next(bool nextDown) { assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); - APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt()); - auto Ret = Tmp.next(nextDown); - *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt()); - return Ret; + // nextDown(x) = -nextUp(-x) + if (nextDown) { + changeSign(); + APFloat::opStatus Result = next(/*nextDown=*/false); + changeSign(); + return Result; + } + switch (getCategory()) { + case fcInfinity: + // nextUp(+inf) = +inf + // nextUp(-inf) = -getLargest() + if (isNegative()) + makeLargest(true); + return opOK; + + case fcNaN: + // IEEE-754R 2008 6.2 Par 2: nextUp(sNaN) = qNaN. Set Invalid flag. + // IEEE-754R 2008 6.2: nextUp(qNaN) = qNaN. Must be identity so we do not + // change the payload. + if (getFirst().isSignaling()) { + // For consistency, propagate the sign of the sNaN to the qNaN. + makeNaN(false, isNegative(), nullptr); + return opInvalidOp; + } + return opOK; + + case fcZero: + // nextUp(pm 0) = +getSmallest() + makeSmallest(false); + return opOK; + + case fcNormal: + break; + } + + const APFloat &HiOld = getFirst(); + const APFloat &LoOld = getSecond(); + + APFloat NextLo = LoOld; + NextLo.next(/*nextDown=*/false); + + // We want to admit values where: + // 1. abs(Lo) <= ulp(Hi)/2 + // 2. Hi == RTNE(Hi + lo) + auto InLattice = [](const APFloat &Hi, const APFloat &Lo) { + return Hi + Lo == Hi; + }; + + // Check if (HiOld, nextUp(LoOld) is in the lattice. + if (InLattice(HiOld, NextLo)) { + // Yes, the result is (HiOld, nextUp(LoOld)). + Floats[1] = std::move(NextLo); + + // TODO: Because we currently rely on semPPCDoubleDoubleLegacy, our maximum + // value is defined to have exactly 106 bits of precision. This limitation + // results in semPPCDoubleDouble being unable to reach its maximum canonical + // value. + DoubleAPFloat Largest{*Semantics, uninitialized}; + Largest.makeLargest(/*Neg=*/false); + if (compare(Largest) == cmpGreaterThan) + makeInf(/*Neg=*/false); + + return opOK; + } + + // Now we need to handle the cases where (HiOld, nextUp(LoOld)) is not the + // correct result. We know the new hi component will be nextUp(HiOld) but our + // lattice rules make it a little ambiguous what the correct NextLo must be. + APFloat NextHi = HiOld; + NextHi.next(/*nextDown=*/false); + + // nextUp(getLargest()) == INFINITY + if (NextHi.isInfinity()) { + makeInf(/*Neg=*/false); + return opOK; + } + + // IEEE 754-2019 5.3.1: + // "If x is the negative number of least magnitude in x's format, nextUp(x) is + // -0." + if (NextHi.isZero()) { + makeZero(/*Neg=*/true); + return opOK; + } + + // abs(NextLo) must be <= ulp(NextHi)/2. We want NextLo to be as close to + // negative infinity as possible. + NextLo = neg(scalbn(harrisonUlp(NextHi), -1, rmTowardZero)); + if (!InLattice(NextHi, NextLo)) + // RTNE may mean that Lo must be < ulp(NextHi) / 2 so we bump NextLo. + NextLo.next(/*nextDown=*/false); + + Floats[0] = std::move(NextHi); + Floats[1] = std::move(NextLo); + + return opOK; } APFloat::opStatus diff --git a/llvm/lib/Support/BLAKE3/CMakeLists.txt b/llvm/lib/Support/BLAKE3/CMakeLists.txt index eae2b02..90311ae 100644 --- a/llvm/lib/Support/BLAKE3/CMakeLists.txt +++ b/llvm/lib/Support/BLAKE3/CMakeLists.txt @@ -26,7 +26,8 @@ endmacro() if (CAN_USE_ASSEMBLER) if (MSVC) check_symbol_exists(_M_X64 "" IS_X64) - if (IS_X64) + check_symbol_exists(_M_ARM64EC "" IS_ARM64EC) + if (IS_X64 AND NOT IS_ARM64EC) enable_language(ASM_MASM) set(LLVM_BLAKE3_ASM_FILES blake3_sse2_x86-64_windows_msvc.asm diff --git a/llvm/lib/Support/FileCollector.cpp b/llvm/lib/Support/FileCollector.cpp index 29436f8..edb5313 100644 --- a/llvm/lib/Support/FileCollector.cpp +++ b/llvm/lib/Support/FileCollector.cpp @@ -313,5 +313,6 @@ private: IntrusiveRefCntPtr<vfs::FileSystem> FileCollector::createCollectorVFS(IntrusiveRefCntPtr<vfs::FileSystem> BaseFS, std::shared_ptr<FileCollector> Collector) { - return new FileCollectorFileSystem(std::move(BaseFS), std::move(Collector)); + return makeIntrusiveRefCnt<FileCollectorFileSystem>(std::move(BaseFS), + std::move(Collector)); } diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc index 277247e..cc02cae 100644 --- a/llvm/lib/Support/Unix/Path.inc +++ b/llvm/lib/Support/Unix/Path.inc @@ -1190,7 +1190,7 @@ Expected<size_t> readNativeFile(file_t FD, MutableArrayRef<char> Buf) { size_t Size = Buf.size(); #endif ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size); - if (ssize_t(NumRead) == -1) + if (NumRead == -1) return errorCodeToError(errnoAsErrorCode()); // The underlying operation on these platforms allow opening directories // for reading in more cases than other platforms. diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index e489282..5d42488 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -397,7 +397,8 @@ void RealFileSystem::printImpl(raw_ostream &OS, PrintType Type, } IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() { - static IntrusiveRefCntPtr<FileSystem> FS(new RealFileSystem(true)); + static IntrusiveRefCntPtr<FileSystem> FS = + makeIntrusiveRefCnt<RealFileSystem>(true); return FS; } @@ -2217,9 +2218,9 @@ RedirectingFileSystem::create(std::unique_ptr<MemoryBuffer> Buffer, std::unique_ptr<RedirectingFileSystem> RedirectingFileSystem::create( ArrayRef<std::pair<std::string, std::string>> RemappedFiles, - bool UseExternalNames, FileSystem &ExternalFS) { + bool UseExternalNames, llvm::IntrusiveRefCntPtr<FileSystem> ExternalFS) { std::unique_ptr<RedirectingFileSystem> FS( - new RedirectingFileSystem(&ExternalFS)); + new RedirectingFileSystem(ExternalFS)); FS->UseExternalNames = UseExternalNames; StringMap<RedirectingFileSystem::Entry *> Entries; @@ -2228,7 +2229,7 @@ std::unique_ptr<RedirectingFileSystem> RedirectingFileSystem::create( SmallString<128> From = StringRef(Mapping.first); SmallString<128> To = StringRef(Mapping.second); { - auto EC = ExternalFS.makeAbsolute(From); + auto EC = ExternalFS->makeAbsolute(From); (void)EC; assert(!EC && "Could not make absolute path"); } @@ -2250,7 +2251,7 @@ std::unique_ptr<RedirectingFileSystem> RedirectingFileSystem::create( } assert(Parent && "File without a directory?"); { - auto EC = ExternalFS.makeAbsolute(To); + auto EC = ExternalFS->makeAbsolute(To); (void)EC; assert(!EC && "Could not make absolute path"); } diff --git a/llvm/lib/Support/Windows/Threading.inc b/llvm/lib/Support/Windows/Threading.inc index d862dbd..b11f216 100644 --- a/llvm/lib/Support/Windows/Threading.inc +++ b/llvm/lib/Support/Windows/Threading.inc @@ -106,7 +106,69 @@ void llvm::get_thread_name(SmallVectorImpl<char> &Name) { Name.clear(); } +namespace llvm::sys::windows { +HMODULE loadSystemModuleSecure(LPCWSTR lpModuleName) { + // Ensure we load indeed a module from system32 path. + // As per GetModuleHandle documentation: + // "If lpModuleName does not include a path and there is more than one loaded + // module with the same base name and extension, you cannot predict which + // module handle will be returned.". This mitigates + // https://learn.microsoft.com/en-us/security-updates/securityadvisories/2010/2269637 + SmallVector<wchar_t, MAX_PATH> Buf; + size_t Size = MAX_PATH; + do { + Buf.resize_for_overwrite(Size); + SetLastError(NO_ERROR); + Size = ::GetSystemDirectoryW(Buf.data(), Buf.size()); + if (Size == 0) + return NULL; + + // Try again with larger buffer. + } while (Size > Buf.size()); + + Buf.truncate(Size); + Buf.push_back(L'\\'); + Buf.append(lpModuleName, lpModuleName + std::wcslen(lpModuleName)); + Buf.push_back(0); + + return ::GetModuleHandleW(Buf.data()); +} +} // namespace llvm::sys::windows + SetThreadPriorityResult llvm::set_thread_priority(ThreadPriority Priority) { +#ifdef THREAD_POWER_THROTTLING_CURRENT_VERSION + HMODULE kernelM = llvm::sys::windows::loadSystemModuleSecure(L"kernel32.dll"); + if (kernelM) { + // SetThreadInformation is only available on Windows 8 and later. Since we + // still support compilation on Windows 7, we load the function dynamically. + typedef BOOL(WINAPI * SetThreadInformation_t)( + HANDLE hThread, THREAD_INFORMATION_CLASS ThreadInformationClass, + _In_reads_bytes_(ThreadInformationSize) PVOID ThreadInformation, + ULONG ThreadInformationSize); + static const auto pfnSetThreadInformation = + (SetThreadInformation_t)::GetProcAddress(kernelM, + "SetThreadInformation"); + if (pfnSetThreadInformation) { + auto setThreadInformation = [](ULONG ControlMaskAndStateMask) { + THREAD_POWER_THROTTLING_STATE state{}; + state.Version = THREAD_POWER_THROTTLING_CURRENT_VERSION; + state.ControlMask = ControlMaskAndStateMask; + state.StateMask = ControlMaskAndStateMask; + return pfnSetThreadInformation( + ::GetCurrentThread(), ThreadPowerThrottling, &state, sizeof(state)); + }; + + // Use EcoQoS for ThreadPriority::Background available (running on most + // efficent cores at the most efficient cpu frequency): + // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadinformation + // https://learn.microsoft.com/en-us/windows/win32/procthread/quality-of-service + setThreadInformation(Priority == ThreadPriority::Background + ? THREAD_POWER_THROTTLING_EXECUTION_SPEED + : 0); + } + } +#endif + // https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-setthreadpriority // Begin background processing mode. The system lowers the resource scheduling // priorities of the thread so that it can perform background work without |