about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2009-05-21 18:47:59 -0700
committerPetr Baudis <pasky@suse.cz>2009-05-22 19:06:26 +0200
commit5d45e59ea6c702ffbd15476e121a4feca7bc93d0 (patch)
tree7c398d23d27248fdd43c2307aa12a3692c9a330b
parent127bcb269a4f04f571c038c1cda8551c87a73500 (diff)
downloadglibc-5d45e59ea6c702ffbd15476e121a4feca7bc93d0.tar.gz
glibc-5d45e59ea6c702ffbd15476e121a4feca7bc93d0.tar.xz
glibc-5d45e59ea6c702ffbd15476e121a4feca7bc93d0.zip
Fix IA-64 memchr read-ahead.
The latest stratcliff extension exposed a bug in the IA-64 memchr which
uses non-speculative loads to prefetch data.  Change the code to use
speculative loads with appropriate fixup.  Fixes BZ 10162.
(cherry picked from commit fa64b7f76b97930cd2aaf7bfd305cac3d925cd8f)
-rw-r--r--ChangeLog5
-rw-r--r--sysdeps/ia64/memchr.S17
2 files changed, 21 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index c527543dbd..6ad9ad8ed8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-05-21  H.J. Lu  <hongjiu.lu@intel.com>
+
+	[BZ #10162]
+	* sysdeps/ia64/memchr.S: Use speculative load.
+
 2009-05-21  Ulrich Drepper  <drepper@redhat.com>
 
 	* sysdeps/unix/sysv/linux/kernel-features.h: Don't define
diff --git a/sysdeps/ia64/memchr.S b/sysdeps/ia64/memchr.S
index e9a7ba8230..cd062b2dd5 100644
--- a/sysdeps/ia64/memchr.S
+++ b/sysdeps/ia64/memchr.S
@@ -96,7 +96,8 @@ ENTRY(__memchr)
 	mov	pr.rot = 1 << 16 ;;
 .l2:
 (p[0])		mov	addr[0] = ret0
-(p[0])		ld8	value[0] = [ret0], 8
+(p[0])		ld8.s	value[0] = [ret0], 8	 // speculative load
+(p[MEMLAT])	chk.s	value[MEMLAT], .recovery // check and recovery
 (p[MEMLAT])	xor	aux[0] = value[MEMLAT], chrx8
 (p[MEMLAT+1])	czx1.r	poschr[0] = aux[1]
 (p[MEMLAT+2])	cmp.ne	p7, p0 = 8, poschr[1]
@@ -124,6 +125,20 @@ ENTRY(__memchr)
 	mov	ar.lc = saved_lc
 	br.ret.sptk.many b0
 
+.recovery:
+	adds	ret0 = -((MEMLAT + 1) * 8), ret0;;
+(p[MEMLAT+1])	add	ret0 = -8, ret0;;
+(p[MEMLAT+2])	add	ret0 = -8, ret0;;
+.l4:
+	mov     addr[MEMLAT+2] = ret0
+	ld8	tmp = [ret0];;		// load the first unchecked 8byte
+	xor	aux[1] = tmp, chrx8;;
+	czx1.r	poschr[1] = aux[1];;
+	cmp.ne	p7, p0 = 8, poschr[1]
+(p7)	br.cond.spnt	.foundit;;
+	adds	ret0 = 8, ret0		// load the next unchecked 8byte
+	br.sptk	.l4;;
+
 END(__memchr)
 
 weak_alias (__memchr, memchr)