From be82d3ec0c651a6d70a6535068fb04072c31c250 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 15 Sep 2016 22:05:08 +0000 Subject: [codeview] Optimize the size of defranges with gaps For small, discontiguous local variable regions, CodeView can use a single defrange record with a gap, rather than having two defrange records. I expect that this optimization will only have a minor impact on debug info size. llvm-svn: 281664 --- llvm/lib/MC/MCCodeView.cpp | 48 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) (limited to 'llvm/lib/MC/MCCodeView.cpp') diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp index acea1ecb2b4..ec5dc20a13e 100644 --- a/llvm/lib/MC/MCCodeView.cpp +++ b/llvm/lib/MC/MCCodeView.cpp @@ -453,16 +453,41 @@ void CodeViewContext::encodeDefRange(MCAsmLayout &Layout, Fixups.clear(); raw_svector_ostream OS(Contents); - // Write down each range where the variable is defined. + // Compute all the sizes up front. + SmallVector, 4> GapAndRangeSizes; + const MCSymbol *LastLabel = nullptr; for (std::pair Range : Frag.getRanges()) { + unsigned GapSize = + LastLabel ? computeLabelDiff(Layout, LastLabel, Range.first) : 0; unsigned RangeSize = computeLabelDiff(Layout, Range.first, Range.second); + GapAndRangeSizes.push_back({GapSize, RangeSize}); + LastLabel = Range.second; + } + + // Write down each range where the variable is defined. + for (size_t I = 0, E = Frag.getRanges().size(); I != E;) { + // If the range size of multiple consecutive ranges is under the max, + // combine the ranges and emit some gaps. + const MCSymbol *RangeBegin = Frag.getRanges()[I].first; + unsigned RangeSize = GapAndRangeSizes[I].second; + size_t J = I + 1; + for (; J != E; ++J) { + unsigned GapAndRangeSize = GapAndRangeSizes[J].first + GapAndRangeSizes[J].second; + if (RangeSize + GapAndRangeSize > MaxDefRange) + break; + RangeSize += GapAndRangeSize; + } + unsigned NumGaps = J - I - 1; + + support::endian::Writer LEWriter(OS); + unsigned Bias = 0; // We must split the range into chunks of MaxDefRange, this is a fundamental // limitation of the file format. do { uint16_t Chunk = std::min((uint32_t)MaxDefRange, RangeSize); - const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Range.first, Ctx); + const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(RangeBegin, Ctx); const MCBinaryExpr *BE = MCBinaryExpr::createAdd(SRE, MCConstantExpr::create(Bias, Ctx), Ctx); MCValue Res; @@ -473,8 +498,8 @@ void CodeViewContext::encodeDefRange(MCAsmLayout &Layout, StringRef FixedSizePortion = Frag.getFixedSizePortion(); // Our record is a fixed sized prefix and a LocalVariableAddrRange that we // are artificially constructing. - size_t RecordSize = - FixedSizePortion.size() + sizeof(LocalVariableAddrRange); + size_t RecordSize = FixedSizePortion.size() + + sizeof(LocalVariableAddrRange) + 4 * NumGaps; // Write out the recrod size. support::endian::Writer(OS).write(RecordSize); // Write out the fixed size prefix. @@ -487,12 +512,25 @@ void CodeViewContext::encodeDefRange(MCAsmLayout &Layout, Fixups.push_back(MCFixup::create(Contents.size(), BE, FK_SecRel_2)); Contents.resize(Contents.size() + 2); // Fixup for section index. // Write down the range's extent. - support::endian::Writer(OS).write(Chunk); + LEWriter.write(Chunk); // Move on to the next range. Bias += Chunk; RangeSize -= Chunk; } while (RangeSize > 0); + + // Emit the gaps afterwards. + assert((NumGaps == 0 || Bias < MaxDefRange) && + "large ranges should not have gaps"); + unsigned GapStartOffset = GapAndRangeSizes[I].second; + for (++I; I != J; ++I) { + unsigned GapSize, RangeSize; + assert(I < GapAndRangeSizes.size()); + std::tie(GapSize, RangeSize) = GapAndRangeSizes[I]; + LEWriter.write(GapStartOffset); + LEWriter.write(RangeSize); + GapStartOffset += GapSize + RangeSize; + } } } -- cgit v1.2.3