Within cp/parser.c, cp_lexer_peek_token and the rest of the
token-related functions are bloated by lexer-debugging code, code that
is completely dead unless calls to the functions
cp_lexer_[start|stop]_debugging are deliberately inserted somewhere in
the parser source code for temporary debugging purposes.

The compiler doesn't fold away this dead code at compile time because it
cannot prove that the flag lexer->debugging_p doesn't change.  So we end
up with this dead debugging code, guarded by cp_lexer_debugging_p, in
the release binary.  This is especially wasteful with code like

 while (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
        && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
        && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
        && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))

which, after inlining, ought to be equivalent to:

 token = parser->lexer->token;
 while (token != CPP_EQ
        && token != CPP_COMMA
        && token != CPP_CLOSE_PAREN
        && token != CPP_EOF)

but because of the lexer-debugging stuff getting in the way of
inlining/CSE, the final code is much worse.

This patch helps the compiler to fold away calls to cp_lexer_debugging_p
when the lexer is not being debugged, by adding a new macro that
short-circuits the cp_lexer_debugging_p predicate.

This change reduces the size of parser.o by 3.5% -- from 6060 Kb to 5852
Kb.  This change also reduces the time it takes to compile a dummy C++
file of mine from 1.95s to 1.85s, a reduction of 5%.

Bootstrapped + regtested on x86_64-pc-linux-gnu.  Does this patch look
OK to commit?

gcc/cp/ChangeLog:

        PR c++/24208
        * parser.c (LEXER_DEBUGGING_ENABLED_P): New macro.
        (cp_lexer_debugging_p): Use it.
        (cp_lexer_start_debugging): Likewise.
        (cp_lexer_stop_debugging): Likewise.
---
 gcc/cp/parser.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 33f1df3..d03b0c9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -706,11 +706,21 @@ cp_lexer_destroy (cp_lexer *lexer)
   ggc_free (lexer);
 }
 
+/* This needs to be set to TRUE before the lexer-debugging infrastructure can
+   be used.  The point of this flag is to help the compiler to fold away calls
+   to cp_lexer_debugging_p within this source file at compile time, when the
+   lexer is not being debugged.  */
+
+#define LEXER_DEBUGGING_ENABLED_P false
+
 /* Returns nonzero if debugging information should be output.  */
 
 static inline bool
 cp_lexer_debugging_p (cp_lexer *lexer)
 {
+  if (!LEXER_DEBUGGING_ENABLED_P)
+    return false;
+
   return lexer->debugging_p;
 }
 
@@ -1296,6 +1306,10 @@ debug (cp_token *ptr)
 static void
 cp_lexer_start_debugging (cp_lexer* lexer)
 {
+  if (!LEXER_DEBUGGING_ENABLED_P)
+    fatal_error (input_location,
+                "LEXER_DEBUGGING_ENABLED_P is not set to true");
+
   lexer->debugging_p = true;
   cp_lexer_debug_stream = stderr;
 }
@@ -1305,6 +1319,10 @@ cp_lexer_start_debugging (cp_lexer* lexer)
 static void
 cp_lexer_stop_debugging (cp_lexer* lexer)
 {
+  if (!LEXER_DEBUGGING_ENABLED_P)
+    fatal_error (input_location,
+                "LEXER_DEBUGGING_ENABLED_P is not set to true");
+
   lexer->debugging_p = false;
   cp_lexer_debug_stream = NULL;
 }
-- 
2.7.0.134.gf5046bd.dirty

Reply via email to