middle-end/111821 - compile-time/memory-hog with large copy

Message ID 20240802125005.36BBE13999@imap1.dmz-prg2.suse.org
State Committed
Commit 8f3d0c8c3dd02d94635517c68fd314cbceed8373
Headers
Series middle-end/111821 - compile-time/memory-hog with large copy |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed

Commit Message

Richard Biener Aug. 2, 2024, 12:50 p.m. UTC
  The following fixes a compile-time/memory-hog when performing a
large aggregate copy to a small object allocated to a register.
While store_bit_field_1 called by store_integral_bit_field will
do nothign for accesses outside of the target the loop over the
source in store_integral_bit_field will still code-generate
the read parts for all words in the source.  The following copies
the noop condition from store_bit_field_1 and terminates the
loop when it runs forward or avoid code-generating the read parts
when not.

Bootstrapped and tested on x86_64-unknown-linux-gnu, OK?

Thanks,
Richard.

	PR middle-end/111821
	* expmed.cc (store_integral_bit_field): Terminate the
	word-wise copy loop when we get out of the destination
	and do a forward copy.  Skip the word if it would be
	outside of the destination in case of a backward copy.

	* gcc.dg/torture/pr111821.c: New testcase.
---
 gcc/expmed.cc                           | 12 ++++++++++++
 gcc/testsuite/gcc.dg/torture/pr111821.c |  9 +++++++++
 2 files changed, 21 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr111821.c
  

Comments

Jeff Law Aug. 5, 2024, 2:18 p.m. UTC | #1
On 8/2/24 6:50 AM, Richard Biener wrote:
> The following fixes a compile-time/memory-hog when performing a
> large aggregate copy to a small object allocated to a register.
> While store_bit_field_1 called by store_integral_bit_field will
> do nothign for accesses outside of the target the loop over the
> source in store_integral_bit_field will still code-generate
> the read parts for all words in the source.  The following copies
> the noop condition from store_bit_field_1 and terminates the
> loop when it runs forward or avoid code-generating the read parts
> when not.
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu, OK?
> 
> Thanks,
> Richard.
> 
> 	PR middle-end/111821
> 	* expmed.cc (store_integral_bit_field): Terminate the
> 	word-wise copy loop when we get out of the destination
> 	and do a forward copy.  Skip the word if it would be
> 	outside of the destination in case of a backward copy.
> 
> 	* gcc.dg/torture/pr111821.c: New testcase.
OK
jeff
  

Patch

diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index 154964bd068..2ca93e30e8f 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -986,6 +986,18 @@  store_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode,
 	    = backwards ^ reverse
 	      ? MAX ((int) bitsize - (i + 1) * BITS_PER_WORD, 0)
 	      : i * BITS_PER_WORD;
+
+	  /* No further action is needed if the target is a register and if
+	     this field lies completely outside that register.  */
+	  if (REG_P (op0) && known_ge (bitnum + bit_offset,
+				       GET_MODE_BITSIZE (GET_MODE (op0))))
+	    {
+	      if (backwards ^ reverse)
+		continue;
+	      /* For forward operation we are finished.  */
+	      return true;
+	    }
+
 	  /* Starting word number in the value.  */
 	  const unsigned int wordnum
 	    = backwards
diff --git a/gcc/testsuite/gcc.dg/torture/pr111821.c b/gcc/testsuite/gcc.dg/torture/pr111821.c
new file mode 100644
index 00000000000..eec6eed6c8e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr111821.c
@@ -0,0 +1,9 @@ 
+/* { dg-do compile } */
+
+typedef union { char a[__INT_MAX__ / 4]; } T;
+unsigned short f(const void *p)
+{
+  unsigned short v;
+  *(T *)(void *)(&v) = *(const T *)p;
+  return v;
+}