mirror of
https://github.com/zeux/pugixml.git
synced 2024-12-31 00:13:01 +08:00
Optimize unrolled scanning for MSVC
While gcc and clang can eliminate dependency on s in the inner loop of PUGI__SCANWHILE_UNROLL, MSVC emits a series of register increments. Rewriting the code to explicitly remove the dependency keeps similar codegen on gcc/clang but improves codegen on MSVC for a 10% performance boost. Also use unrolled scanning in text_output_escaped (2% faster). git-svn-id: https://pugixml.googlecode.com/svn/trunk@1048 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
8a402b480f
commit
42219590f3
@ -1916,7 +1916,7 @@ PUGI__NS_BEGIN
|
||||
#define PUGI__POPNODE() { cursor = cursor->parent; }
|
||||
#define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; }
|
||||
#define PUGI__SCANWHILE(X) { while (X) ++s; }
|
||||
#define PUGI__SCANWHILE_UNROLL(X) { while (X) { ++s; if (PUGI__UNLIKELY(!(X))) break; ++s; if (PUGI__UNLIKELY(!(X))) break; ++s; if (PUGI__UNLIKELY(!(X))) break; ++s; } }
|
||||
#define PUGI__SCANWHILE_UNROLL(X) { for (;;) { char_t ss = s[0]; if (PUGI__UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI__UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI__UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI__UNLIKELY(!(X))) { s += 3; break; } s += 4; } }
|
||||
#define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; }
|
||||
#define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast<char_t*>(0)
|
||||
#define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); }
|
||||
@ -1927,7 +1927,7 @@ PUGI__NS_BEGIN
|
||||
|
||||
while (true)
|
||||
{
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(*s, ct_parse_comment));
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_comment));
|
||||
|
||||
if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair
|
||||
{
|
||||
@ -1955,7 +1955,7 @@ PUGI__NS_BEGIN
|
||||
|
||||
while (true)
|
||||
{
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(*s, ct_parse_cdata));
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_cdata));
|
||||
|
||||
if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair
|
||||
{
|
||||
@ -1989,7 +1989,7 @@ PUGI__NS_BEGIN
|
||||
|
||||
while (true)
|
||||
{
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(*s, ct_parse_pcdata));
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_pcdata));
|
||||
|
||||
if (*s == '<') // PCDATA ends here
|
||||
{
|
||||
@ -2069,7 +2069,7 @@ PUGI__NS_BEGIN
|
||||
|
||||
while (true)
|
||||
{
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(*s, ct_parse_attr_ws | ct_space));
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space));
|
||||
|
||||
if (*s == end_quote)
|
||||
{
|
||||
@ -2110,7 +2110,7 @@ PUGI__NS_BEGIN
|
||||
|
||||
while (true)
|
||||
{
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(*s, ct_parse_attr_ws));
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws));
|
||||
|
||||
if (*s == end_quote)
|
||||
{
|
||||
@ -2146,7 +2146,7 @@ PUGI__NS_BEGIN
|
||||
|
||||
while (true)
|
||||
{
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(*s, ct_parse_attr));
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr));
|
||||
|
||||
if (*s == end_quote)
|
||||
{
|
||||
@ -2178,7 +2178,7 @@ PUGI__NS_BEGIN
|
||||
|
||||
while (true)
|
||||
{
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(*s, ct_parse_attr));
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr));
|
||||
|
||||
if (*s == end_quote)
|
||||
{
|
||||
@ -2580,7 +2580,7 @@ PUGI__NS_BEGIN
|
||||
|
||||
cursor->name = s;
|
||||
|
||||
PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(*s, ct_symbol)); // Scan for a terminator.
|
||||
PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator.
|
||||
PUGI__ENDSEG(); // Save char in 'ch', terminate & step over.
|
||||
|
||||
if (ch == '>')
|
||||
@ -2601,7 +2601,7 @@ PUGI__NS_BEGIN
|
||||
|
||||
a->name = s; // Save the offset.
|
||||
|
||||
PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(*s, ct_symbol)); // Scan for a terminator.
|
||||
PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator.
|
||||
PUGI__CHECK_ERROR(status_bad_attribute, s); //$ redundant, left for performance
|
||||
|
||||
PUGI__ENDSEG(); // Save char in 'ch', terminate & step over.
|
||||
@ -3257,7 +3257,7 @@ PUGI__NS_BEGIN
|
||||
const char_t* prev = s;
|
||||
|
||||
// While *s is a usual symbol
|
||||
while (!PUGI__IS_CHARTYPEX(*s, type)) ++s;
|
||||
PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPEX(ss, type));
|
||||
|
||||
writer.write_buffer(prev, static_cast<size_t>(s - prev));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user