diff options
author | Richard Biener <rguenther@suse.de> | 2024-08-02 13:49:34 +0200 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2024-08-06 09:33:12 +0200 |
commit | 8f3d0c8c3dd02d94635517c68fd314cbceed8373 (patch) | |
tree | 05d5a9f1f54ef349905c2081588ba335aaaf9fb8 | |
parent | 3592d3f8cc4b89ae508c747a46a626d73cb9616d (diff) | |
download | gcc-8f3d0c8c3dd02d94635517c68fd314cbceed8373.zip gcc-8f3d0c8c3dd02d94635517c68fd314cbceed8373.tar.gz gcc-8f3d0c8c3dd02d94635517c68fd314cbceed8373.tar.bz2 |
middle-end/111821 - compile-time/memory-hog with large copy
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.
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.
-rw-r--r-- | gcc/expmed.cc | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr111821.c | 9 |
2 files changed, 21 insertions, 0 deletions
diff --git a/gcc/expmed.cc b/gcc/expmed.cc index 154964b..2ca93e3 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 0000000..eec6eed --- /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; +} |