This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH RFA: libcpp speedup patch: tweak _cpp_clean_line
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 28 Dec 2006 15:07:03 -0800
- Subject: PATCH RFA: libcpp speedup patch: tweak _cpp_clean_line
Profiling the preprocessor shows that most of the time is spent in
_cpp_clean_line. This patch tweaks that function to run slightly
faster. I added calls to __builtin_expect in a few places; these
reduce the main loop to a few compact instructions. When there is a
space at the end of the line, instead of always walking backward
looking for a backslash, we instead only walk backward if we saw a
backslash earlier; since we know there is a backslash, the loop
condition when walking backward is simplified.
In conjunction with the patches to c-common.c and to libcpp/files.c
which I already sent, this gave me an 18% reduction in time required
to run the preprocessor on a large C++ file.
Tested with a C/C++ bootstrap and testsuite run on i686-pc-linux-gnu.
OK for mainline?
Ian
2006-12-28 Ian Lance Taylor <iant@google.com>
* lex.c (_cpp_clean_line): Add uses of __builtin_expect. Don't
look backward at the end of the line unless we saw a backslash.
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c (revision 120236)
+++ libcpp/lex.c (working copy)
@@ -111,31 +111,39 @@ _cpp_clean_line (cpp_reader *pfile)
if (!buffer->from_stage3)
{
+ const uchar *pbackslash = NULL;
+
/* Short circuit for the common case of an un-escaped line with
no trigraphs. The primary win here is by not writing any
data back to memory until we have to. */
for (;;)
{
c = *++s;
- if (c == '\n' || c == '\r')
+ if (__builtin_expect (c == '\n', 0)
+ || __builtin_expect (c == '\r', 0))
{
d = (uchar *) s;
- if (s == buffer->rlimit)
+ if (__builtin_expect (s == buffer->rlimit, 0))
goto done;
/* DOS line ending? */
- if (c == '\r' && s[1] == '\n')
- s++;
+ if (__builtin_expect (c == '\r', 0)
+ && s[1] == '\n')
+ {
+ s++;
+ if (s == buffer->rlimit)
+ goto done;
+ }
- if (s == buffer->rlimit)
+ if (__builtin_expect (pbackslash == NULL, 1))
goto done;
/* check for escaped newline */
p = d;
- while (p != buffer->next_line && is_nvspace (p[-1]))
+ while (is_nvspace (p[-1]))
p--;
- if (p == buffer->next_line || p[-1] != '\\')
+ if (p - 1 != pbackslash)
goto done;
/* Have an escaped newline; process it and proceed to
@@ -145,7 +153,11 @@ _cpp_clean_line (cpp_reader *pfile)
buffer->next_line = p - 1;
break;
}
- if (c == '?' && s[1] == '?' && _cpp_trigraph_map[s[2]])
+ if (__builtin_expect (c == '\\', 0))
+ pbackslash = s;
+ else if (__builtin_expect (c == '?', 0)
+ && __builtin_expect (s[1] == '?', 0)
+ && _cpp_trigraph_map[s[2]])
{
/* Have a trigraph. We may or may not have to convert
it. Add a line note regardless, for -Wtrigraphs. */