diff options
| author | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2014-10-04 05:03:33 +0000 | 
|---|---|---|
| committer | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2014-10-04 05:03:33 +0000 | 
| commit | 42219590f3ea1e88e41f8250da5a123f3a9236b2 (patch) | |
| tree | 060acf61be3252d7e5b42550b79a6268b8acc079 /src | |
| parent | 8a402b480fc88efec8ce0897fb6cdddac147992d (diff) | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/pugixml.cpp | 22 | 
1 files changed, 11 insertions, 11 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 6506a5e..55dd8ec 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -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));  | 
