re PR rtl-optimization/66152 (suboptimal load bytes to stack)
authorJakub Jelinek <jakub@redhat.com>
Sat, 16 Feb 2019 11:20:33 +0000 (12:20 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 16 Feb 2019 11:20:33 +0000 (12:20 +0100)
PR rtl-optimization/66152
* builtins.h (c_readstr): Declare.
* builtins.c (c_readstr): Remove forward declaration.  Add
null_terminated_p argument, if false, read all bytes from the
string instead of stopping after '\0'.
* expr.c (string_cst_read_str): New function.
(store_expr): Use string_cst_read_str instead of
builtin_strncpy_read_str.  Try to store by pieces the whole
exp_len first, and only if that fails, split it up into
store by pieces followed by clear_storage.  Formatting fix.

* gcc.target/i386/pr66152.c: New test.

From-SVN: r268957

gcc/ChangeLog
gcc/builtins.c
gcc/builtins.h
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr66152.c [new file with mode: 0644]

index a63f2abba13f8fabb2ae6c9a3ece98602517f142..addbd3999322a89b4d90eae1ee78818f0a354e9b 100644 (file)
@@ -1,5 +1,16 @@
 2019-02-16  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/66152
+       * builtins.h (c_readstr): Declare.
+       * builtins.c (c_readstr): Remove forward declaration.  Add
+       null_terminated_p argument, if false, read all bytes from the
+       string instead of stopping after '\0'.
+       * expr.c (string_cst_read_str): New function.
+       (store_expr): Use string_cst_read_str instead of
+       builtin_strncpy_read_str.  Try to store by pieces the whole
+       exp_len first, and only if that fails, split it up into
+       store by pieces followed by clear_storage.  Formatting fix.
+
        * config/i386/i386.md (*movqi_internal): Remove static from
        buf variable.  Use output_asm_insn (buf, operands); return "";
        instead of return buf;.
index 693e8937918a72d8ee0bfb4dae75346e2c9dec55..6f266ad15d0afb6c7672fe2e262ec1d12e2d383f 100644 (file)
@@ -95,7 +95,6 @@ builtin_info_type builtin_info[(int)END_BUILTINS];
 /* Non-zero if __builtin_constant_p should be folded right away.  */
 bool force_folding_builtin_constant_p;
 
-static rtx c_readstr (const char *, scalar_int_mode);
 static int target_char_cast (tree, char *);
 static rtx get_memory_rtx (tree, tree);
 static int apply_args_size (void);
@@ -802,10 +801,14 @@ c_strlen (tree src, int only_value, c_strlen_data *data, unsigned eltsize)
 }
 
 /* Return a constant integer corresponding to target reading
-   GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
+   GET_MODE_BITSIZE (MODE) bits from string constant STR.  If
+   NULL_TERMINATED_P, reading stops after '\0' character, all further ones
+   are assumed to be zero, otherwise it reads as many characters
+   as needed.  */
 
-static rtx
-c_readstr (const char *str, scalar_int_mode mode)
+rtx
+c_readstr (const char *str, scalar_int_mode mode,
+          bool null_terminated_p/*=true*/)
 {
   HOST_WIDE_INT ch;
   unsigned int i, j;
@@ -830,7 +833,7 @@ c_readstr (const char *str, scalar_int_mode mode)
        j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
       j *= BITS_PER_UNIT;
 
-      if (ch)
+      if (ch || !null_terminated_p)
        ch = (unsigned char) str[i];
       tmp[j / HOST_BITS_PER_WIDE_INT] |= ch << (j % HOST_BITS_PER_WIDE_INT);
     }
index 599c96e72e166abee803dce2464dd0e60452258c..1ffb491d7850366c74bd694bf9e1c277bcde1da9 100644 (file)
@@ -103,6 +103,7 @@ struct c_strlen_data
 };
 
 extern tree c_strlen (tree, int, c_strlen_data * = NULL, unsigned = 1);
+extern rtx c_readstr (const char *, scalar_int_mode, bool = true);
 extern void expand_builtin_setjmp_setup (rtx, rtx);
 extern void expand_builtin_setjmp_receiver (rtx);
 extern void expand_builtin_update_setjmp_buf (rtx);
index 01ddf5a41bdbf9de83a540324bea1c3a7063b99e..ce71ae710898444ea34b491ac6a98f8e25e01295 100644 (file)
@@ -5453,6 +5453,30 @@ emit_storent_insn (rtx to, rtx from)
   return maybe_expand_insn (code, 2, ops);
 }
 
+/* Helper function for store_expr storing of STRING_CST.  */
+
+static rtx
+string_cst_read_str (void *data, HOST_WIDE_INT offset, scalar_int_mode mode)
+{
+  tree str = (tree) data;
+
+  gcc_assert (offset >= 0);
+  if (offset >= TREE_STRING_LENGTH (str))
+    return const0_rtx;
+
+  if ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
+      > (unsigned HOST_WIDE_INT) TREE_STRING_LENGTH (str))
+    {
+      char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
+      size_t l = TREE_STRING_LENGTH (str) - offset;
+      memcpy (p, TREE_STRING_POINTER (str) + offset, l);
+      memset (p + l, '\0', GET_MODE_SIZE (mode) - l);
+      return c_readstr (p, mode, false);
+    }
+
+  return c_readstr (TREE_STRING_POINTER (str) + offset, mode, false);
+}
+
 /* Generate code for computing expression EXP,
    and storing the value into TARGET.
 
@@ -5472,7 +5496,7 @@ emit_storent_insn (rtx to, rtx from)
 
 rtx
 store_expr (tree exp, rtx target, int call_param_p,
-                       bool nontemporal, bool reverse)
+           bool nontemporal, bool reverse)
 {
   rtx temp;
   rtx alt_rtl = NULL_RTX;
@@ -5606,36 +5630,32 @@ store_expr (tree exp, rtx target, int call_param_p,
       if (TREE_STRING_LENGTH (str) <= 0)
        goto normal_expr;
 
-      str_copy_len = strlen (TREE_STRING_POINTER (str));
-      if (str_copy_len < TREE_STRING_LENGTH (str) - 1)
-       goto normal_expr;
+      if (can_store_by_pieces (exp_len, string_cst_read_str, (void *) str,
+                              MEM_ALIGN (target), false))
+       {
+         store_by_pieces (target, exp_len, string_cst_read_str, (void *) str,
+                          MEM_ALIGN (target), false, RETURN_BEGIN);
+         return NULL_RTX;
+       }
 
       str_copy_len = TREE_STRING_LENGTH (str);
-      if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0
-         && TREE_STRING_POINTER (str)[TREE_STRING_LENGTH (str) - 1] == '\0')
+      if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0)
        {
          str_copy_len += STORE_MAX_PIECES - 1;
          str_copy_len &= ~(STORE_MAX_PIECES - 1);
        }
-      str_copy_len = MIN (str_copy_len, exp_len);
-      if (!can_store_by_pieces (str_copy_len, builtin_strncpy_read_str,
-                               CONST_CAST (char *, TREE_STRING_POINTER (str)),
-                               MEM_ALIGN (target), false))
+      if (str_copy_len >= exp_len)
+       goto normal_expr;
+
+      if (!can_store_by_pieces (str_copy_len, string_cst_read_str,
+                               (void *) str, MEM_ALIGN (target), false))
        goto normal_expr;
 
-      dest_mem = target;
-
-      memop_ret retmode = exp_len > str_copy_len ? RETURN_END : RETURN_BEGIN;
-      dest_mem = store_by_pieces (dest_mem,
-                                 str_copy_len, builtin_strncpy_read_str,
-                                 CONST_CAST (char *,
-                                             TREE_STRING_POINTER (str)),
-                                 MEM_ALIGN (target), false,
-                                 retmode);
-      if (exp_len > str_copy_len)
-       clear_storage (adjust_address (dest_mem, BLKmode, 0),
-                      GEN_INT (exp_len - str_copy_len),
-                      BLOCK_OP_NORMAL);
+      dest_mem = store_by_pieces (target, str_copy_len, string_cst_read_str,
+                                 (void *) str, MEM_ALIGN (target), false,
+                                 RETURN_END);
+      clear_storage (adjust_address (dest_mem, BLKmode, 0),
+                    GEN_INT (exp_len - str_copy_len), BLOCK_OP_NORMAL);
       return NULL_RTX;
     }
   else
index 7fa8da548bd6646916f74d1ce73a981009dfd32d..ebc75cef578cb5a13e21ef4c02a0f4f116314dcc 100644 (file)
@@ -1,3 +1,8 @@
+2019-02-16  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/66152
+       * gcc.target/i386/pr66152.c: New test.
+
 2019-02-15  Eric Botcazou  <ebotcazou@adacore.com>
 
        * g++.dg/asan/asan_oob_test.cc: Skip OOB_int on SPARC.
diff --git a/gcc/testsuite/gcc.target/i386/pr66152.c b/gcc/testsuite/gcc.target/i386/pr66152.c
new file mode 100644 (file)
index 0000000..3d152eb
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR rtl-optimization/66152 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "movabs\[^\n\r]*506097522914230528" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movabs\[^\n\r]*505813836079825408" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "mov\[^\n\r]*50462976" { target ia32 } } } */
+/* { dg-final { scan-assembler "mov\[^\n\r]*117835012" { target ia32 } } } */
+/* { dg-final { scan-assembler "mov\[^\n\r]*100925952" { target ia32 } } } */
+/* { dg-final { scan-assembler "mov\[^\n\r]*117768961" { target ia32 } } } */
+
+void foo (char *);
+
+void
+bar (void)
+{
+  char a[] = {0,1,2,3,4,5,6,7};
+  foo (a);
+}
+
+void
+baz (void)
+{
+  char a[8] = "\0\2\4\6\1\3\5\7";
+  foo (a);
+}