From: Aaron Sawdey Date: Mon, 13 Feb 2017 16:00:22 +0000 (+0000) Subject: re PR target/79449 (ppc builtin expansion of strncmp can cross page (4k) boundary... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8d6427c6ddefb12bf5656e8938f8055a1201650a;p=gcc.git re PR target/79449 (ppc builtin expansion of strncmp can cross page (4k) boundary where it should not) 2017-02-13 Aaron Sawdey PR target/79449 * gcc.dg/strncmp-2.c: New. Test strncmp and memcmp builtin expansion for reading beyond a 4k boundary. 2017-02-13 Aaron Sawdey PR target/79449 * config/rs6000/rs6000.c (expand_block_compare): Make sure runtime boundary crossing check and subsequent code generation agree. From-SVN: r245392 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 098b1e61247..f35205119e8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-02-13 Aaron Sawdey + + PR target/79449 + * config/rs6000/rs6000.c (expand_block_compare): Make sure runtime + boundary crossing check and subsequent code generation agree. + 2017-02-13 Kyrylo Tkachov * config/aarch64/aarch64.c (has_memory_op): Delete. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 10cbea97bed..f0824790b7a 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -19931,14 +19931,25 @@ expand_strn_compare (rtx operands[], int no_length) cmpldi cr7,r8,4096-16 bgt cr7,L(pagecross) */ + /* Make sure that the length we use for the alignment test and + the subsequent code generation are in agreement so we do not + go past the length we tested for a 4k boundary crossing. */ + unsigned HOST_WIDE_INT align_test = compare_length; + if (align_test < 8) + { + align_test = HOST_WIDE_INT_1U << ceil_log2 (align_test); + base_align = align_test; + } + else + { + align_test = ROUND_UP (align_test, 8); + base_align = 8; + } + if (align1 < 8) - expand_strncmp_align_check (strncmp_label, src1, compare_length); + expand_strncmp_align_check (strncmp_label, src1, align_test); if (align2 < 8) - expand_strncmp_align_check (strncmp_label, src2, compare_length); - - /* After the runtime alignment checks, we can use any alignment we - like as we know there is no 4k boundary crossing. */ - base_align = 8; + expand_strncmp_align_check (strncmp_label, src2, align_test); /* Now generate the following sequence: - branch to begin_compare diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f4497d5b412..b5e225e2acf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-02-13 Aaron Sawdey + + PR target/79449 + * gcc.dg/strncmp-2.c: New. Test strncmp and memcmp builtin expansion + for reading beyond a 4k boundary. + 2017-02-13 Jakub Jelinek PR rtl-optimization/79388 diff --git a/gcc/testsuite/gcc.dg/strncmp-2.c b/gcc/testsuite/gcc.dg/strncmp-2.c new file mode 100644 index 00000000000..0c9a07aacb7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/strncmp-2.c @@ -0,0 +1,99 @@ +/* Test strncmp builtin expansion for compilation and proper execution. */ +/* { dg-do run { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target ptr32plus } */ + +#include +#include +#include +#include +#include +#include + +int lib_memcmp(const void *a, const void *b, size_t n) asm("memcmp"); +int lib_strncmp(const char *a, const char *b, size_t n) asm("strncmp"); + +static void test_driver_strncmp (void (test_strncmp)(const char *, const char *, int), + void (test_memcmp)(const void *, const void *, int), + size_t sz) +{ + long pgsz = sysconf(_SC_PAGESIZE); + char buf1[sz+1]; + char *buf2 = aligned_alloc(pgsz,2*pgsz); + char *p2; + int r,i,e; + + r = mprotect (buf2+pgsz,pgsz,PROT_NONE); + if (r < 0) abort(); + + memset(buf1,'A',sz); + for(i=10; i>=0; i--) { + p2 = buf2+pgsz-sz-i; + memset(p2,'A',sz); + e = lib_strncmp(buf1,p2,sz); + (*test_strncmp)(buf1,p2,e); + e = lib_memcmp(buf1,p2,sz); + (*test_memcmp)(buf1,p2,e); + } +} + +#define RUN_TEST(SZ) test_driver_strncmp (test_strncmp_ ## SZ, test_memcmp_ ## SZ, SZ); + +#define DEF_TEST(SZ) \ +__attribute__((noinline)) \ +void test_strncmp_ ## SZ (const char *str1, const char *str2, int expect) \ +{ \ + int r; \ + r = strncmp(str1,str2,SZ); \ + if ( r < 0 && !(expect < 0) ) abort(); \ + if ( r > 0 && !(expect > 0) ) abort(); \ + if ( r == 0 && !(expect == 0) ) abort(); \ +} \ +__attribute__((noinline)) \ +void test_memcmp_ ## SZ (const void *p1, const void *p2, int expect) \ +{ \ + int r; \ + r = memcmp(p1,p2,SZ); \ + if ( r < 0 && !(expect < 0) ) abort(); \ + if ( r > 0 && !(expect > 0) ) abort(); \ + if ( r == 0 && !(expect == 0) ) abort(); \ +} + +DEF_TEST(1) +DEF_TEST(2) +DEF_TEST(3) +DEF_TEST(4) +DEF_TEST(5) +DEF_TEST(6) +DEF_TEST(7) +DEF_TEST(8) +DEF_TEST(9) +DEF_TEST(10) +DEF_TEST(11) +DEF_TEST(12) +DEF_TEST(13) +DEF_TEST(14) +DEF_TEST(15) +DEF_TEST(16) + +int +main(int argc, char **argv) +{ + RUN_TEST(1) ; + RUN_TEST(2) ; + RUN_TEST(3) ; + RUN_TEST(4) ; + RUN_TEST(5) ; + RUN_TEST(6) ; + RUN_TEST(7) ; + RUN_TEST(8) ; + RUN_TEST(9) ; + RUN_TEST(10); + RUN_TEST(11); + RUN_TEST(12); + RUN_TEST(13); + RUN_TEST(14); + RUN_TEST(15); + RUN_TEST(16); + return 0; +}