diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 249ee283504535b87bc4f7052f5bb139acbbeabd..caf85d197560931ba86b6a7b17a4f4ff8f218a19 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2013-06-20  Richard Biener  <rguenther@suse.de>
+
+	* data-streamer-in.c (streamer_read_uhwi): Optimize single
+	byte case, inline streamer_read_uchar and defer section
+	overrun check.
+
 2013-06-20  Richard Biener  <rguenther@suse.de>
 
 	PR tree-optimization/57584
diff --git a/gcc/data-streamer-in.c b/gcc/data-streamer-in.c
index e9ceb29312a3ea962cd2dc5b86b6b3cccac5ab01..93fe2ff4c3b6219049b0581209d569f2ca5ff641 100644
--- a/gcc/data-streamer-in.c
+++ b/gcc/data-streamer-in.c
@@ -120,18 +120,33 @@ bp_unpack_string (struct data_in *data_in, struct bitpack_d *bp)
 unsigned HOST_WIDE_INT
 streamer_read_uhwi (struct lto_input_block *ib)
 {
-  unsigned HOST_WIDE_INT result = 0;
-  int shift = 0;
+  unsigned HOST_WIDE_INT result;
+  int shift;
   unsigned HOST_WIDE_INT byte;
+  unsigned int p = ib->p;
+  unsigned int len = ib->len;
 
-  while (true)
+  const char *data = ib->data;
+  result = data[p++];
+  if ((result & 0x80) != 0)
     {
-      byte = streamer_read_uchar (ib);
-      result |= (byte & 0x7f) << shift;
-      shift += 7;
-      if ((byte & 0x80) == 0)
-	return result;
+      result &= 0x7f;
+      shift = 7;
+      do
+	{
+	  byte = data[p++];
+	  result |= (byte & 0x7f) << shift;
+	  shift += 7;
+	}
+      while ((byte & 0x80) != 0);
     }
+
+  /* We check for section overrun after the fact for performance reason.  */
+  if (p > len)
+    lto_section_overrun (ib);
+
+  ib->p = p;
+  return result;
 }