ce426f
    Backport of
ce426f
    commit 72607db038df1a1a7987af814aad8d2ed466c45c
ce426f
    Author: Rajalakshmi Srinivasaraghavan <raji@linux.vnet.ibm.com>
ce426f
    Date:   Fri Jan 9 11:56:35 2015 -0500
ce426f
    
ce426f
        powerpc: Optimize POWER7 strcmp trailing checks
ce426f
    
ce426f
        This patch optimized the POWER7 trailing check by avoiding using byte
ce426f
        read operations and instead use the doubleword already readed with
ce426f
        bitwise operations.
ce426f
    
ce426f
        ChangeLog:
ce426f
    	2015-01-13  Rajalakshmi Srinivasaraghavan  <raji@linux.vnet.ibm.com>
ce426f
    		    Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
ce426f
    
ce426f
    	* sysdeps/powerpc/powerpc64/power7/strcmp.S (strcmp): Optimize
ce426f
    	trailing byte check.
ce426f
ce426f
diff --git a/sysdeps/powerpc/powerpc64/power7/strcmp.S b/sysdeps/powerpc/powerpc64/power7/strcmp.S
ce426f
index f16a9d8..ade2811 100644
ce426f
--- a/sysdeps/powerpc/powerpc64/power7/strcmp.S
ce426f
+++ b/sysdeps/powerpc/powerpc64/power7/strcmp.S
ce426f
@@ -25,122 +25,96 @@
ce426f
 
ce426f
 /* int [r3] strcmp (const char *s1 [r3], const char *s2 [r4])  */
ce426f
 
ce426f
+	.machine	power7
ce426f
 EALIGN (strcmp, 4, 0)
ce426f
 	CALL_MCOUNT 2
ce426f
 
ce426f
 	or r9, r3, r4
ce426f
 	rldicl. r10, r9, 0, 61	/* are s1 and s2 8 byte aligned..?  */
ce426f
 	bne cr0, L(process_unaligned_bytes)
ce426f
+	li	r5, 0
ce426f
 
ce426f
+	.align 4
ce426f
 /* process input parameters on double word aligned boundary  */
ce426f
-	ld r9, 0(r4)		/* load s2 at offset=0  */
ce426f
-	li r10, 0		/* load mask=0  */
ce426f
-	cmpb r10, r9, r10	/* compare bytes at s2 with mask  */
ce426f
-	cmpdi cr7, r10, 0	/* is NULL found ..? is end of string HIT  */
ce426f
-	bne cr7, L(process_unaligned_bytes)	/* process byte by byte  */
ce426f
-
ce426f
-	ld r10, 0(r3)		/* load s1 at offset=0  */
ce426f
-	li r8, 0		/* load mask=0  */
ce426f
-	cmpb r8, r10, r8	/* compare bytes at s1 with mask  */
ce426f
-	cmpdi cr7, r8, 0	/* is NULL found ..? is end of string HIT  */
ce426f
-	bne cr7, L(process_unaligned_bytes)	/* process byte by byte  */
ce426f
-
ce426f
-/*s1 and s2 does not contain NULL now , so compare all 8 bytes in a GO  */
ce426f
-	cmpb r9, r10, r9	/* compare s1 and s2  */
ce426f
-	cmpdi cr7, r9, -1	/* compare result with 0xFFFFFFFFFFFFFFFF  */
ce426f
-	bne cr7, L(process_unaligned_bytes)	/* s1,s2 mismatch found  */
ce426f
-
ce426f
-	addi r5, r3, 8		/* save next offset of s2  */
ce426f
-	addi r11, r4, 8		/* save next offset of s1  */
ce426f
-	ld r8, 8(r4)		/* load s2 at offset=8  */
ce426f
-	li r9, 0		/* load mask=0  */
ce426f
-	cmpb r9, r8, r9		/* compare bytes at s2 with mask  */
ce426f
-	cmpdi cr7, r9, 0	/* NULL found ..?  */
ce426f
-	bne cr7, L(processBytes)/* update input and process bytes one by one  */
ce426f
-
ce426f
-	mr r9, r4		/* save s2  */
ce426f
-	li r10, 0		/* load mask=0  */
ce426f
-
ce426f
-	ld r7, 8(r3)		/* load s1 at offset=8  */
ce426f
-	cmpb r6, r7, r10	/* compare bytes at s1 with mask  */
ce426f
-	cmpdi cr7, r6, 0	/* is NULL found  */
ce426f
-	bne cr7, L(processBytes)/* mismatch, so process one by one  */
ce426f
-
ce426f
 L(unrollDword):
ce426f
-	cmpb r8, r7, r8		/* compare s1 and s2  */
ce426f
-	cmpdi cr7, r8, -1	/* compare result with 0xFFFFFFFFFFFFFFFF  */
ce426f
-	bne cr7, L(processBytes)/* mismatch with s1 and s2  */
ce426f
-
ce426f
-	addi r5, r3, 16		/* save offset=16 of s1  */
ce426f
-	addi r4, r9, 16		/* save offset=16 of s2  */
ce426f
-	ld r8, 16(r9)		/* load s2 at offset=16  */
ce426f
-	cmpb r7, r8, r10	/* compare bytes at s2 with mask  */
ce426f
-	cmpdi cr7, r7, 0	/* NULL found  ..?  */
ce426f
-	bne cr7, L(update2processBytes)
ce426f
-
ce426f
-	ld r7, 16(r3)		/* load s1 at offset=16  */
ce426f
-	cmpb r6, r7, r10	/* check s1 for end of string  */
ce426f
-	cmpdi cr7, r6, 0	/* end of s1 ?,then handle byte by byte  */
ce426f
-	bne 7,L(update2processBytes)
ce426f
-
ce426f
-	cmpb r8, r7, r8		/* compare s1 and s2 double words  */
ce426f
-	cmpdi cr7, r8, -1	/* compare results with 0xFFFFFFFFFFFFFFFF  */
ce426f
-	bne cr7,L(update2processBytes)
ce426f
-
ce426f
-	addi r5, r3, 24		/* update s1 to offset=24  */
ce426f
-	addi r4, r9, 24		/* update s2 to offset=24  */
ce426f
-
ce426f
-	ld r8, 24(r9)		/* load s2  */
ce426f
-	cmpb r7, r8, r10	/* compare s2 for NULL  */
ce426f
-	cmpdi cr7, r7, 0	/* verify if s2 is ending now  */
ce426f
-	bne cr7,L(update2processBytes)
ce426f
-
ce426f
-	ld r7, 24(r3)		/* load s1 at offset=24  */
ce426f
-	cmpb r6, r7, r10	/* verify for NULL  */
ce426f
-	cmpdi cr7, r6, 0	/* is NULL found  */
ce426f
-	bne cr7, L(update2processBytes)
ce426f
-
ce426f
-	cmpb r8, r7, r8		/* compare s1 and s2  */
ce426f
-	cmpdi cr7, r8, -1	/* are s1 and s2 same ..?  */
ce426f
-	bne cr7, L(update2processBytes)
ce426f
-
ce426f
-	addi r7, r9, 32		/* update s2 to next double word  */
ce426f
-	addi r3, r3, 32		/* update s1 to next double word  */
ce426f
-
ce426f
-	ld r8, 32(r9)		/* load s2  */
ce426f
-	mr r4, r7		/* save s2  */
ce426f
-	cmpb r6, r8, r10	/* compare s2 with NULL  */
ce426f
-	cmpdi cr7, r6, 0	/* end of s2 ..? */
ce426f
-	bne cr7, L(process_unaligned_bytes)
ce426f
-
ce426f
-	ld r6, 0(r3)		/* load and compare s1 for NULL  */
ce426f
-	cmpb r5, r6, r10
ce426f
-	cmpdi cr7, r5, 0
ce426f
-	bne cr7, L(process_unaligned_bytes)
ce426f
-
ce426f
-	cmpb r8, r6, r8		/* compare s1 and s2  */
ce426f
-	cmpdi cr7, r8, -1
ce426f
-	bne cr7, L(process_unaligned_bytes)
ce426f
-
ce426f
-	addi r5, r3, 8		/* increment s1 and d2 here  */
ce426f
-	addi r11, r9, 40
ce426f
-
ce426f
-	ld r8, 40(r9)		/* process s2 now  */
ce426f
-	cmpb r9, r8, r10
ce426f
-	cmpdi cr7, r9, 0
ce426f
-	bne cr7, L(processBytes)
ce426f
-
ce426f
-	mr r9, r7
ce426f
-	ld r7, 8(r3)		/* process s1 now  */
ce426f
-	cmpb r6, r7, r10
ce426f
-	cmpdi cr7, r6, 0
ce426f
-	beq cr7, L(unrollDword)	/* unroll to compare s1 and s2  */
ce426f
-
ce426f
-L(processBytes):
ce426f
-	mr r4, r11		/* update input params  */
ce426f
-	mr r3, r5
ce426f
-
ce426f
-	.p2align 4
ce426f
+	ld	r8,0(r3)
ce426f
+	ld	r10,0(r4)
ce426f
+	cmpb	r7,r8,r5
ce426f
+	cmpdi	cr7,r7,0
ce426f
+	mr	r9,r7
ce426f
+	bne 	cr7,L(null_found)
ce426f
+	cmpld	cr7,r8,r10
ce426f
+	bne	cr7,L(different)
ce426f
+
ce426f
+	ld	r8,8(r3)
ce426f
+	ld	r10,8(r4)
ce426f
+	cmpb	r7,r8,r5
ce426f
+	cmpdi	cr7,r7,0
ce426f
+	mr	r9,r7
ce426f
+	bne 	cr7,L(null_found)
ce426f
+	cmpld	cr7,r8,r10
ce426f
+	bne	cr7,L(different)
ce426f
+
ce426f
+	ld	r8,16(r3)
ce426f
+	ld	r10,16(r4)
ce426f
+	cmpb	r7,r8,r5
ce426f
+	cmpdi	cr7,r7,0
ce426f
+	mr	r9,r7
ce426f
+	bne 	cr7,L(null_found)
ce426f
+	cmpld	cr7,r8,r10
ce426f
+	bne	cr7,L(different)
ce426f
+
ce426f
+	ld	r8,24(r3)
ce426f
+	ld	r10,24(r4)
ce426f
+	cmpb	r7,r8,r5
ce426f
+	cmpdi	cr7,r7,0
ce426f
+	mr	r9,r7
ce426f
+	bne 	cr7,L(null_found)
ce426f
+	cmpld	cr7,r8,r10
ce426f
+	bne	cr7,L(different)
ce426f
+
ce426f
+	addi r3, r3, 32
ce426f
+	addi r4, r4, 32
ce426f
+	beq cr7, L(unrollDword)
ce426f
+
ce426f
+	.align 4
ce426f
+L(null_found):
ce426f
+#ifdef __LITTLE_ENDIAN__
ce426f
+	neg	r7,r9
ce426f
+	and	r9,r9,r7
ce426f
+	li	r7,-1
ce426f
+	cntlzd	r9,r9
ce426f
+	subfic	r9,r9,71
ce426f
+	sld	r9,r7,r9
ce426f
+#else
ce426f
+	cntlzd	r9,r9
ce426f
+	li	r7,-1
ce426f
+	addi	r9,r9,8
ce426f
+	srd	r9,r7,r9
ce426f
+#endif
ce426f
+	or	r8,r8,r9
ce426f
+	or	r10,r10,r9
ce426f
+
ce426f
+L(different):
ce426f
+	cmpb	r9,r8,r10
ce426f
+#ifdef __LITTLE_ENDIAN__
ce426f
+	addi	r7,r9,1
ce426f
+	andc	r9,r7,r9
ce426f
+	cntlzd	r9,r9
ce426f
+	subfic	r9,r9,63
ce426f
+#else
ce426f
+	not	r9,r9
ce426f
+	cntlzd	r9,r9
ce426f
+	subfic	r9,r9,56
ce426f
+#endif
ce426f
+	srd	r3,r8,r9
ce426f
+	srd	r10,r10,r9
ce426f
+	rldicl	r10,r10,0,56
ce426f
+	rldicl	r3,r3,0,56
ce426f
+	subf	r3,r10,r3
ce426f
+	blr
ce426f
+
ce426f
+	.align 4
ce426f
 L(process_unaligned_bytes):
ce426f
 	lbz r9, 0(r3)		/* load byte from s1  */
ce426f
 	lbz r10, 0(r4)		/* load byte from s2  */
ce426f
@@ -172,24 +146,19 @@ L(process_unaligned_bytes):
ce426f
 	addi r4, r4, 4		/* increment s2 by unroll factor  */
ce426f
 	beq cr6, L(process_unaligned_bytes)	/* unroll byte processing  */
ce426f
 
ce426f
-	.p2align 4
ce426f
+	.align 4
ce426f
 L(ComputeDiff):
ce426f
 	extsw r9, r9
ce426f
 	subf r10, r10, r9	/* compute s1 - s2  */
ce426f
 	extsw r3, r10
ce426f
 	blr			/* return  */
ce426f
 
ce426f
-	.p2align 4
ce426f
+	.align 4
ce426f
 L(diffOfNULL):
ce426f
 	li r9, 0
ce426f
 	subf r10, r10, r9	/* compute s1 - s2  */
ce426f
 	extsw r3, r10		/* sign extend result  */
ce426f
 	blr			/* return  */
ce426f
 
ce426f
-	.p2align 4
ce426f
-L(update2processBytes):
ce426f
-	mr r3, r5		/* update and proceed  */
ce426f
-	b L(process_unaligned_bytes)
ce426f
-
ce426f
 END (strcmp)
ce426f
 libc_hidden_builtin_def (strcmp)