This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, rs6000] Fix libcpp/lex.c Altivec code to be correct for little endian
- From: Bill Schmidt <wschmidt at linux dot vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: dje dot gcc at gmail dot com, uweigand at de dot ibm dot com
- Date: Sun, 17 Nov 2013 19:33:34 -0600
- Subject: [PATCH, rs6000] Fix libcpp/lex.c Altivec code to be correct for little endian
- Authentication-results: sourceware.org; auth=none
Hi,
As Ulrich Weigand discovered, libcpp/lex.c contains some code optimized
for use with Altivec that is incorrect for little endian targets. This
breaks bootstrap on powerpc64le-unknown-linux-gnu when configured with
--with-cpu=power7.
This patch makes appropriate modifications for little endian. The
transformation of lvsr/vperm(x,y,z) into lvsl/vperm(y,x,z) is familiar
from a previous patch. The other obvious change is converting
count-leading-zeroes into count-trailing-zeroes.
Bootstrapped on powerpc64-unknown-linux-gnu (BE) using --with-cpu=power7
with no regressions. Bootstrap for powerpc64le-unknown-linux-gnu (LE)
using --with-cpu=power7 now completes with this patch. There are still
failures for --with-cpu=power7 that are not present using
--with-cpu=power6 that need to be investigated, but they are unrelated
to this change.
Ok for trunk?
Thanks,
Bill
2013-11-17 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
* lex.c (search_line_fast): Correct for little endian.
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c (revision 204928)
+++ libcpp/lex.c (working copy)
@@ -559,8 +559,13 @@ search_line_fast (const uchar *s, const uchar *end
beginning with all ones and shifting in zeros according to the
mis-alignment. The LVSR instruction pulls the exact shift we
want from the address. */
+#ifdef __BIG_ENDIAN__
mask = __builtin_vec_lvsr(0, s);
mask = __builtin_vec_perm(zero, ones, mask);
+#else
+ mask = __builtin_vec_lvsl(0, s);
+ mask = __builtin_vec_perm(ones, zero, mask);
+#endif
data &= mask;
/* While altivec loads mask addresses, we still need to align S so
@@ -624,7 +629,11 @@ search_line_fast (const uchar *s, const uchar *end
/* L now contains 0xff in bytes for which we matched one of the
relevant characters. We can find the byte index by finding
its bit index and dividing by 8. */
+#ifdef __BIG_ENDIAN__
l = __builtin_clzl(l) >> 3;
+#else
+ l = __builtin_ctzl(l) >> 3;
+#endif
return s + l;
#undef N