This is an archive of the discontinued LLVM Phabricator instance.

Keep history of macro definitions and #undefs
ClosedPublic

Authored by alexfh on Aug 23 2012, 10:53 PM.

Details

Summary

Summary: Keep history of macro definitions and #undefs with corresponding source locations, so that we can later find out all macros active in a specified source location. We don't save the history in PCH (no need currently). Memory overhead is about sizeof(void*)*3*<number of macro definitions and #undefs>+<in-memory size of all #undef'd macros>

I've run a test on a file composed of 109 .h files from boost 1.49 on x86-64 linux.
Stats before this patch:

  • Preprocessor Stats:

73222 directives found:

19171 #define.
4345 #undef.
#include/#include_next/#import:
  5233 source files entered.
  27 max include stack depth
19210 #if/#ifndef/#ifdef.
2384 #else/#elif.
6891 #endif.
408 #pragma.

14466 #if/#ifndef#ifdef regions skipped
80023/451669/1270 obj/fn/builtin macros expanded, 85724 on the fast path.
127145 token paste (##) operations performed, 11008 on the fast path.

Preprocessor Memory: 5874615B total

BumpPtr: 4399104
Macro Expanded Tokens: 417768
Predefines Buffer: 8135
Macros: 1048576
#pragma push_macro Info: 0
Poison Reasons: 1024
Comment Handlers: 8

Stats with this patch:
...
Preprocessor Memory: 7541687B total

BumpPtr: 6066176
Macro Expanded Tokens: 417768
Predefines Buffer: 8135
Macros: 1048576
#pragma push_macro Info: 0
Poison Reasons: 1024
Comment Handlers: 8

In my test increase in memory usage is about 1.7Mb, which is ~28% of initial preprocessor's memory usage and about 0.8% of clang's total VMM allocation.

As for CPU overhead, it should only be noticeable when iterating over all macros, and should mostly consist of couple extra dereferences and one comparison per macro + skipping of #undef'd macros. It's less trivial to measure, though, as the preprocessor consumes a very small fraction of compilation time.

Diff Detail

Event Timeline

alexfh updated this revision to Unknown Object (????).Aug 23 2012, 11:08 PM

more context lines in diff

doug.gregor requested changes to this revision.Aug 24 2012, 8:59 AM

Thanks for working on this! Some comments inline.

tools/clang/include/clang/Lex/Preprocessor.h
476

Why do we need the definition location in the MacroInfoList? For #defines, the location is already in the MacroInfo. For #undefs, it would seem to be more valuable to simply model the #undef as a

SourceLocation UndefLocation;

within the MacroInfo itself. An active macro will have an invalid UndefLocation.

478

This is really a link to the previously-defined macro, right?

tools/clang/lib/Lex/PPMacroExpansion.cpp
62

llvm_unreachable?

tools/clang/lib/Sema/SemaCodeComplete.cpp
2907

Eventually, we'd want to be able to look back to the macro definition that was actually active at the point of code completion (even if that macro has since been #undef'd). Please add a FIXME for this.

7174

This is a code completion after, e.g., #ifdef, so any macro name we know about---even if it's been #undef'd---is completely reasonable here.

tools/clang/lib/Serialization/ASTWriter.cpp
1679

We need to store the macro history, because whether one uses a PCH file should impact only the performance of the front end, not the actual meaning of the compiler's data structures.

The (currently stalled, but ongoing) work on modules actually needs this macro history information, too.

Sending the new patch right after this comment.

tools/clang/include/clang/Lex/Preprocessor.h
476

This serves as bot #define and #undef location. I think this should simplify code using this structure. But maybe the name would better be just 'Location' or 'DefUndefLocation' or something like that. What do you think?

478

It's 'Next' in terms of linked list, but I could make it 'Previous' if you like ;)

tools/clang/lib/Lex/PPMacroExpansion.cpp
62

Yep. Done.

tools/clang/lib/Sema/SemaCodeComplete.cpp
2907

Done.

7174

Reverted this.

tools/clang/lib/Serialization/ASTWriter.cpp
1679

Added FIXME.

alexfh updated this revision to Unknown Object (????).Aug 24 2012, 10:21 AM

Addressed Doug's comments.

alexfh updated this revision to Unknown Object (????).Aug 27 2012, 7:16 PM

Removed MacroInfoList, added PreviousDeclaration and UndefLocation to MacroInfo.

After I posted this patch, I found, that it has a bug with macro redefinition handling. Will fix later today or tomorrow. But, please, still look at other things.

alexfh updated this revision to Unknown Object (????).Aug 28 2012, 9:57 AM

Fixed issue with pragma push_macro/pop_macro

I'll leave the real review to Doug, but I have a tiny style nit. ;]

tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp
571–579

FYI, please use the conventional naming for loop iterators in Clang/LLVM: I and E.

alexfh updated this revision to Unknown Object (????).Aug 28 2012, 12:13 PM

It, End -> I, E

doug.gregor accepted this revision.Aug 28 2012, 4:29 PM

This is fine. We should tackle (de-)serialization separately.

alexfh closed this revision.Aug 28 2012, 5:21 PM

I've made a quick-and-dirty performance measurement using almost all boost
1.51 headers. The test source file, script and execution logs are attached.
Clang was built with gcc (hence log names).

TL;DR: changes 'caused by the patch: preprocessor memory usage 5.9M ->7.4M,
total time: no measurable difference (both about 4.8s).

As for the test input, I consider it quite a heavy load on preprocessor:

  • Preprocessor Stats:

75165 directives found:

19499 #define.
4433 #undef.
#include/#include_next/#import:
  5357 source files entered.
  27 max include stack depth
19919 #if/#ifndef/#ifdef.
2459 #else/#elif.
7110 #endif.
426 #pragma.

14996 #if/#ifndef#ifdef regions skipped
82955/459701/1316 obj/fn/builtin macros expanded, 88278 on the fast path.
129361 token paste (##) operations performed, 11361 on the fast path.

Difference between execution logs:

diff clang-gcc-perf-before-patch.log clang-gcc-perf-with-patch.log
193,194c193,194
< Preprocessor Memory: 5940151B total

< BumpPtr: 4464640

Preprocessor Memory: 7394231B total

BumpPtr: 5918720

229c229

< FileID scans: 205598 linear, 2102385 binary.

FileID scans: 205604 linear, 2102345 binary.

239,241c239,241
< real 0m4.872s
< user 0m4.700s

< sys 0m0.160s

real 0m4.796s
user 0m4.560s
sys 0m0.220s

434,435c434,435
< Preprocessor Memory: 5940151B total

< BumpPtr: 4464640

Preprocessor Memory: 7394231B total

BumpPtr: 5918720

480,482c480,482
< real 0m4.819s
< user 0m4.620s

< sys 0m0.180s

real 0m4.882s
user 0m4.730s
sys 0m0.140s

675,676c675,676
< Preprocessor Memory: 5940151B total

< BumpPtr: 4464640

Preprocessor Memory: 7394231B total

BumpPtr: 5918720

711c711

< FileID scans: 205598 linear, 2102365 binary.

FileID scans: 205604 linear, 2102385 binary.

721,723c721,723
< real 0m4.794s
< user 0m4.610s

< sys 0m0.170s

real 0m4.789s
user 0m4.630s
sys 0m0.150s

I've made a quick-and-dirty performance measurement using almost all boost
1.51 headers. The test source file, script and execution logs are attached.
Clang was built with gcc (hence log names).

TL;DR: changes 'caused by the patch: preprocessor memory usage 5.9M ->7.4M,
total time: no measurable difference (both about 4.8s).

As for the test input, I consider it quite a heavy load on preprocessor:

  • Preprocessor Stats:

75165 directives found:

19499 #define.
4433 #undef.
#include/#include_next/#import:
  5357 source files entered.
  27 max include stack depth
19919 #if/#ifndef/#ifdef.
2459 #else/#elif.
7110 #endif.
426 #pragma.

14996 #if/#ifndef#ifdef regions skipped
82955/459701/1316 obj/fn/builtin macros expanded, 88278 on the fast path.
129361 token paste (##) operations performed, 11361 on the fast path.

Difference between execution logs:

diff clang-gcc-perf-before-patch.log clang-gcc-perf-with-patch.log
193,194c193,194
< Preprocessor Memory: 5940151B total

< BumpPtr: 4464640

Preprocessor Memory: 7394231B total

BumpPtr: 5918720

229c229

< FileID scans: 205598 linear, 2102385 binary.

FileID scans: 205604 linear, 2102345 binary.

239,241c239,241
< real 0m4.872s
< user 0m4.700s

< sys 0m0.160s

real 0m4.796s
user 0m4.560s
sys 0m0.220s

434,435c434,435
< Preprocessor Memory: 5940151B total

< BumpPtr: 4464640

Preprocessor Memory: 7394231B total

BumpPtr: 5918720

480,482c480,482
< real 0m4.819s
< user 0m4.620s

< sys 0m0.180s

real 0m4.882s
user 0m4.730s
sys 0m0.140s

675,676c675,676
< Preprocessor Memory: 5940151B total

< BumpPtr: 4464640

Preprocessor Memory: 7394231B total

BumpPtr: 5918720

711c711

< FileID scans: 205598 linear, 2102365 binary.

FileID scans: 205604 linear, 2102385 binary.

721,723c721,723
< real 0m4.794s
< user 0m4.610s

< sys 0m0.170s

real 0m4.789s
user 0m4.630s
sys 0m0.150s