diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index 6506a5e3cac9ef66477696299335d068b180cec5..55dd8eca1eb41576f004890f86a40985edf4b34a 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));