diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/FormatUtil.h b/llvm/include/llvm/DebugInfo/PDB/Native/FormatUtil.h index 76a019ddf8f34..a76b5c0d44791 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/FormatUtil.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/FormatUtil.h @@ -62,49 +62,6 @@ LLVM_ABI std::string formatChunkKind(codeview::DebugSubsectionKind Kind, LLVM_ABI std::string formatSymbolKind(codeview::SymbolKind K); LLVM_ABI std::string formatTypeLeafKind(codeview::TypeLeafKind K); -/// Returns the number of digits in the given integer. -inline int NumDigits(uint64_t N) { - if (N < 10ULL) - return 1; - if (N < 100ULL) - return 2; - if (N < 1000ULL) - return 3; - if (N < 10000ULL) - return 4; - if (N < 100000ULL) - return 5; - if (N < 1000000ULL) - return 6; - if (N < 10000000ULL) - return 7; - if (N < 100000000ULL) - return 8; - if (N < 1000000000ULL) - return 9; - if (N < 10000000000ULL) - return 10; - if (N < 100000000000ULL) - return 11; - if (N < 1000000000000ULL) - return 12; - if (N < 10000000000000ULL) - return 13; - if (N < 100000000000000ULL) - return 14; - if (N < 1000000000000000ULL) - return 15; - if (N < 10000000000000000ULL) - return 16; - if (N < 100000000000000000ULL) - return 17; - if (N < 1000000000000000000ULL) - return 18; - if (N < 10000000000000000000ULL) - return 19; - return 20; -} - namespace detail { template struct EndianAdapter final diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/InputFile.h b/llvm/include/llvm/DebugInfo/PDB/Native/InputFile.h index 71df1d59c2177..1f2c7e43002fa 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/InputFile.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/InputFile.h @@ -183,7 +183,8 @@ Error iterateSymbolGroups(InputFile &Input, const PrintScope &HeaderScope, if (Filters.DumpModi) { uint32_t Modi = *Filters.DumpModi; SymbolGroup SG(&Input, Modi); - return iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(Modi)), + return iterateOneModule(Input, + withLabelWidth(HeaderScope, NumDigitsBase10(Modi)), SG, Modi, Callback); } @@ -191,9 +192,9 @@ Error iterateSymbolGroups(InputFile &Input, const PrintScope &HeaderScope, for (const auto &SG : Input.symbol_groups()) { if (shouldDumpSymbolGroup(I, SG, Filters)) - if (auto Err = - iterateOneModule(Input, withLabelWidth(HeaderScope, NumDigits(I)), - SG, I, Callback)) + if (auto Err = iterateOneModule( + Input, withLabelWidth(HeaderScope, NumDigitsBase10(I)), SG, I, + Callback)) return Err; ++I; diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h index 9bbb8a2a30541..2288c74494c32 100644 --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -786,6 +786,9 @@ using stack_float_t = volatile float; using stack_float_t = float; #endif +/// Returns the number of digits in the given integer. +int NumDigitsBase10(uint64_t X); + } // namespace llvm #endif diff --git a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp index 989fde9749b18..957c0c4c8f9a9 100644 --- a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp +++ b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp @@ -84,7 +84,7 @@ class SourceCode { void format(raw_ostream &OS) { if (!PrunedSource) return; - size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine)); + size_t MaxLineNumberWidth = NumDigitsBase10(LastLine); int64_t L = FirstLine; for (size_t Pos = 0; Pos < PrunedSource->size(); ++L) { size_t PosEnd = PrunedSource->find('\n', Pos); diff --git a/llvm/lib/Support/MathExtras.cpp b/llvm/lib/Support/MathExtras.cpp index ad44b1a21676c..4424cdd935fef 100644 --- a/llvm/lib/Support/MathExtras.cpp +++ b/llvm/lib/Support/MathExtras.cpp @@ -28,4 +28,39 @@ namespace llvm { const float huge_valf = HUGE_VALF; #endif + /// Returns the number of digits in the given integer. + int NumDigitsBase10(uint64_t X) { + static constexpr struct ConstexprData { + uint8_t AtLeast[65] = {}; + uint64_t Boundaries[20] = {}; + static constexpr int NumDigitsConstexpr(uint64_t N) { + int res = 1; + while (N >= 10) { + res++; + N /= 10; + } + return res; + } + constexpr ConstexprData() { + uint64_t Val = ~0ull; + for (uint64_t i = 0; i <= 64; i++) { + uint64_t Digits = NumDigitsConstexpr(Val) - 1; + AtLeast[i] = Digits; + Val >>= 1; + } + // Special case because X=0 should return 1 and not 0 + Boundaries[0] = 0; + Val = 10; + for (uint64_t i = 1; i < 20; i++) { + Boundaries[i] = Val; + Val *= 10; + } + } + } Data; + + uint64_t Base2 = X ? countl_zero(X) : 64; + uint64_t Digits = Data.AtLeast[Base2]; + return Digits + (X >= Data.Boundaries[Digits]); + } + } // namespace llvm diff --git a/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp b/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp index 4c851e14a12dd..3adc6593ac884 100644 --- a/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/BytesOutputStyle.cpp @@ -370,7 +370,7 @@ static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel, Callback); } else { uint32_t Count = Modules.getModuleCount(); - uint32_t Digits = NumDigits(Count); + uint32_t Digits = NumDigitsBase10(Count); for (uint32_t I = 0; I < Count; ++I) { iterateOneModule(File, P, Modules, I, Digits, IndentLevel, Callback); } diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp index b2362ecb75703..5ddc0db8a34c6 100644 --- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp +++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp @@ -363,16 +363,16 @@ Error DumpOutputStyle::dumpStreamSummary() { for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) { P.formatLine( "Stream {0} ({1} bytes): [{2}]", - fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)), + fmt_align(StreamIdx, AlignStyle::Right, NumDigitsBase10(StreamCount)), fmt_align(getPdb().getStreamByteSize(StreamIdx), AlignStyle::Right, - NumDigits(MaxStreamSize)), + NumDigitsBase10(MaxStreamSize)), StreamPurposes[StreamIdx].getLongName()); if (opts::dump::DumpStreamBlocks) { auto Blocks = getPdb().getStreamBlockList(StreamIdx); std::vector BV(Blocks.begin(), Blocks.end()); P.formatLine(" {0} Blocks: [{1}]", - fmt_repeat(' ', NumDigits(StreamCount)), + fmt_repeat(' ', NumDigitsBase10(StreamCount)), make_range(BV.begin(), BV.end())); } } @@ -572,7 +572,7 @@ Error DumpOutputStyle::dumpSymbolStats() { if (StreamIdx == kInvalidStreamIndex) { P.formatLine( "Mod {0} (debug info not present): [{1}]", - fmt_align(Modi, AlignStyle::Right, NumDigits(ModCount)), + fmt_align(Modi, AlignStyle::Right, NumDigitsBase10(ModCount)), Desc.getModuleName()); return Error::success(); } @@ -749,11 +749,11 @@ Error DumpOutputStyle::dumpUdtStats() { // separators. StringRef CountHeader("Count"); StringRef SizeHeader("Size"); - size_t CD = NumDigits(UdtStats.Totals.Count); + size_t CD = NumDigitsBase10(UdtStats.Totals.Count); CD += (CD - 1) / 3; CD = std::max(CD, CountHeader.size()); - size_t SD = NumDigits(UdtStats.Totals.Size); + size_t SD = NumDigitsBase10(UdtStats.Totals.Size); SD += (SD - 1) / 3; SD = std::max(SD, SizeHeader.size()); @@ -1071,7 +1071,7 @@ Error DumpOutputStyle::dumpStringTableFromPdb() { P.formatLine("Empty"); else { auto MaxID = llvm::max_element(IS->name_ids()); - uint32_t Digits = NumDigits(*MaxID); + uint32_t Digits = NumDigitsBase10(*MaxID); P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits), "String"); @@ -1205,7 +1205,8 @@ dumpFullTypeStream(LinePrinter &Printer, LazyRandomTypeCollection &Types, TpiStream *Stream, bool Bytes, bool Extras) { Printer.formatLine("Showing {0:N} records", NumTypeRecords); - uint32_t Width = NumDigits(TypeIndex::FirstNonSimpleIndex + NumTypeRecords); + uint32_t Width = + NumDigitsBase10(TypeIndex::FirstNonSimpleIndex + NumTypeRecords); MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types, RefTracker, NumHashBuckets, HashValues, Stream); @@ -1221,8 +1222,8 @@ static void dumpPartialTypeStream(LinePrinter &Printer, TypeReferenceTracker *RefTracker, TpiStream &Stream, ArrayRef TiList, bool Bytes, bool Extras, bool Deps) { - uint32_t Width = - NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords()); + uint32_t Width = NumDigitsBase10(TypeIndex::FirstNonSimpleIndex + + Stream.getNumTypeRecords()); MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types, RefTracker, Stream.getNumHashBuckets(), Stream.getHashValues(), diff --git a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp index db3a752d58165..5f0f95b3775e6 100644 --- a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp +++ b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp @@ -309,7 +309,7 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, return Error::success(); auto Max = llvm::max_element(Indices); - uint32_t W = NumDigits(Max->getIndex()) + 2; + uint32_t W = NumDigitsBase10(Max->getIndex()) + 2; for (auto I : Indices) P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W), @@ -324,7 +324,7 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, return Error::success(); auto Max = llvm::max_element(Indices); - uint32_t W = NumDigits(Max->getIndex()) + 2; + uint32_t W = NumDigitsBase10(Max->getIndex()) + 2; for (auto I : Indices) P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W), @@ -494,7 +494,7 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, return Error::success(); auto Max = llvm::max_element(Indices); - uint32_t W = NumDigits(Max->getIndex()) + 2; + uint32_t W = NumDigitsBase10(Max->getIndex()) + 2; for (auto I : Indices) P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W), diff --git a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp index 7c8ac474c0fdb..62310440ef4fb 100644 --- a/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp +++ b/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp @@ -111,7 +111,7 @@ static Error tryInstructionMix() { Mix.begin(), Mix.end(), 1, [](unsigned MaxValue, const MixEntry &Elt) { return std::max(MaxValue, Elt.second); }); - unsigned ValueWidth = std::log10(MaxValue) + 1; + unsigned ValueWidth = NumDigitsBase10(MaxValue); FOS << "Instruction"; FOS.PadToColumn(MaxMnemonic + 1) << "Count\n"; FOS << "-----------"; diff --git a/llvm/unittests/Support/MathExtrasTest.cpp b/llvm/unittests/Support/MathExtrasTest.cpp index 5cb85fc55da92..27e8b26e8801d 100644 --- a/llvm/unittests/Support/MathExtrasTest.cpp +++ b/llvm/unittests/Support/MathExtrasTest.cpp @@ -692,4 +692,19 @@ TYPED_TEST(OverflowTest, MulResultZero) { EXPECT_FALSE(MulOverflow(0, -5, Result)); EXPECT_EQ(Result, TypeParam(0)); } + +TEST(MathExtras, NumDigitsBase10) { + EXPECT_EQ(NumDigitsBase10(0), 1); + EXPECT_EQ(NumDigitsBase10(1), 1); + + uint64_t Val = 10; + for (int i = 2; i <= 20; i++) { + EXPECT_EQ(NumDigitsBase10(Val - 1), i - 1); + EXPECT_EQ(NumDigitsBase10(Val), i); + Val *= 10; + } + + EXPECT_EQ(NumDigitsBase10(std::numeric_limits::max()), 20); +} + } // namespace diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp index 305c28b4c7257..1a31d25ab5669 100644 --- a/llvm/utils/FileCheck/FileCheck.cpp +++ b/llvm/utils/FileCheck/FileCheck.cpp @@ -595,7 +595,7 @@ static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req, unsigned LineCount = InputFileText.count('\n'); if (InputFileEnd[-1] != '\n') ++LineCount; - unsigned LineNoWidth = std::log10(LineCount) + 1; + unsigned LineNoWidth = NumDigitsBase10(LineCount); // +3 below adds spaces (1) to the left of the (right-aligned) line numbers // on input lines and (2) to the right of the (left-aligned) labels on // annotation lines so that input lines and annotation lines are more