public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/c++-modules] expander: Optimize store_expr from STRING_CST [PR95052]
@ 2020-06-11 12:56 Nathan Sidwell
  0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2020-06-11 12:56 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:43a4fc095e30188392cc42299c4081297e321104

commit 43a4fc095e30188392cc42299c4081297e321104
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri May 29 10:42:50 2020 +0200

    expander: Optimize store_expr from STRING_CST [PR95052]
    
    In the following testcase, store_expr of e.g. 97 bytes long string literal
    into 1MB long array is implemented by copying the 97 bytes from .rodata
    section, followed by clearing the remaining bytes.  But, as the STRING_CST
    has type char[1024*1024], we actually allocate whole 1MB in .rodata section
    for it, even when we only use the first 97 bytes from that.
    
    The following patch tweaks it so that if we are going to initialize only the
    small part from it, we don't emit all the zeros that we never use after it.
    
    2020-05-29  Jakub Jelinek  <jakub@redhat.com>
    
            PR middle-end/95052
            * expr.c (store_expr): If expr_size is constant and significantly
            larger than TREE_STRING_LENGTH, set temp to just the
            TREE_STRING_LENGTH portion of the STRING_CST.
    
            * gcc.target/i386/pr95052.c: New test.

Diff:
---
 gcc/expr.c                              | 34 ++++++++++++++++++++++++++++++++-
 gcc/testsuite/gcc.target/i386/pr95052.c | 20 +++++++++++++++++++
 2 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/gcc/expr.c b/gcc/expr.c
index dfbeae71518..049d3edf3ad 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5583,6 +5583,7 @@ store_expr (tree exp, rtx target, int call_param_p,
   rtx temp;
   rtx alt_rtl = NULL_RTX;
   location_t loc = curr_insn_location ();
+  bool shortened_string_cst = false;
 
   if (VOID_TYPE_P (TREE_TYPE (exp)))
     {
@@ -5749,7 +5750,32 @@ store_expr (tree exp, rtx target, int call_param_p,
       /* If we want to use a nontemporal or a reverse order store, force the
 	 value into a register first.  */
       tmp_target = nontemporal || reverse ? NULL_RTX : target;
-      temp = expand_expr_real (exp, tmp_target, GET_MODE (target),
+      tree rexp = exp;
+      if (TREE_CODE (exp) == STRING_CST
+	  && tmp_target == target
+	  && GET_MODE (target) == BLKmode
+	  && TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
+	{
+	  rtx size = expr_size (exp);
+	  if (CONST_INT_P (size)
+	      && size != const0_rtx
+	      && (UINTVAL (size)
+		  > ((unsigned HOST_WIDE_INT) TREE_STRING_LENGTH (exp) + 32)))
+	    {
+	      /* If the STRING_CST has much larger array type than
+		 TREE_STRING_LENGTH, only emit the TREE_STRING_LENGTH part of
+		 it into the rodata section as the code later on will use
+		 memset zero for the remainder anyway.  See PR95052.  */
+	      tmp_target = NULL_RTX;
+	      rexp = copy_node (exp);
+	      tree index
+		= build_index_type (size_int (TREE_STRING_LENGTH (exp) - 1));
+	      TREE_TYPE (rexp) = build_array_type (TREE_TYPE (TREE_TYPE (exp)),
+						   index);
+	      shortened_string_cst = true;
+	    }
+	}
+      temp = expand_expr_real (rexp, tmp_target, GET_MODE (target),
 			       (call_param_p
 				? EXPAND_STACK_PARM : EXPAND_NORMAL),
 			       &alt_rtl, false);
@@ -5763,6 +5789,7 @@ store_expr (tree exp, rtx target, int call_param_p,
       && TREE_CODE (exp) != ERROR_MARK
       && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
     {
+      gcc_assert (!shortened_string_cst);
       if (GET_MODE_CLASS (GET_MODE (target))
 	  != GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp)))
 	  && known_eq (GET_MODE_BITSIZE (GET_MODE (target)),
@@ -5815,6 +5842,7 @@ store_expr (tree exp, rtx target, int call_param_p,
     {
       if (GET_MODE (temp) != GET_MODE (target) && GET_MODE (temp) != VOIDmode)
 	{
+	  gcc_assert (!shortened_string_cst);
 	  if (GET_MODE (target) == BLKmode)
 	    {
 	      /* Handle calls that return BLKmode values in registers.  */
@@ -5900,6 +5928,8 @@ store_expr (tree exp, rtx target, int call_param_p,
 		emit_label (label);
 	    }
 	}
+      else if (shortened_string_cst)
+	gcc_unreachable ();
       /* Handle calls that return values in multiple non-contiguous locations.
 	 The Irix 6 ABI has examples of this.  */
       else if (GET_CODE (target) == PARALLEL)
@@ -5929,6 +5959,8 @@ store_expr (tree exp, rtx target, int call_param_p,
 	    emit_move_insn (target, temp);
 	}
     }
+  else
+    gcc_assert (!shortened_string_cst);
 
   return NULL_RTX;
 }
diff --git a/gcc/testsuite/gcc.target/i386/pr95052.c b/gcc/testsuite/gcc.target/i386/pr95052.c
new file mode 100644
index 00000000000..1bbfd7ea305
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr95052.c
@@ -0,0 +1,20 @@
+/* PR middle-end/95052 */
+/* { dg-do compile } */
+/* { dg-options "-Os -mtune=skylake" } */
+/* Verify we don't waste almost 2 megabytes of .rodata.  */
+/* { dg-final { scan-assembler-not "\.zero\t1048\[0-9]\[0-9]\[0-9]" } } */
+extern void foo (char *, unsigned);
+
+int
+main ()
+{
+  char str[1024 * 1024] =
+    "fooiuhluhpiuhliuhliyfyukyfklyugkiuhpoipoipoipoipoipoipoipoipoipoipoipoipoimipoipiuhoulouihnliuhl";
+  char arr[1024 * 1024] =
+    { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 6, 2, 3,
+      4, 5, 6, 7, 8, 9, 0, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6,
+      7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+  foo (str, sizeof (str));
+  foo (arr, sizeof (arr));
+  return 0;
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-06-11 12:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-11 12:56 [gcc/devel/c++-modules] expander: Optimize store_expr from STRING_CST [PR95052] Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).