diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-07-25 07:44:57 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-07-25 07:44:57 +0000 |
commit | 4237b215bbb0c0a5b8795bad99857c2f00501bb1 (patch) | |
tree | c7fe34fd006f2ff66fbe4a743da4b4b825b9c156 /gcc | |
parent | ec9fb89b6fac647441c49b44091933732bcc5c26 (diff) | |
download | gcc-4237b215bbb0c0a5b8795bad99857c2f00501bb1.tar.gz |
2014-07-25 Richard Biener <rguenther@suse.de>
PR middle-end/61762
PR middle-end/61894
* fold-const.c (native_encode_int): Add and handle offset
parameter to do partial encodings of expr.
(native_encode_fixed): Likewise.
(native_encode_real): Likewise.
(native_encode_complex): Likewise.
(native_encode_vector): Likewise.
(native_encode_string): Likewise.
(native_encode_expr): Likewise.
* fold-const.c (native_encode_expr): Add offset parameter
defaulting to -1.
* gimple-fold.c (fold_string_cst_ctor_reference): Remove.
(fold_ctor_reference): Handle all reads from tcc_constant
ctors.
* gcc.dg/pr61762.c: New testcase.
* gcc.dg/fold-cstring.c: Likewise.
* gcc.dg/fold-cvect.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@213045 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/fold-const.c | 105 | ||||
-rw-r--r-- | gcc/fold-const.h | 2 | ||||
-rw-r--r-- | gcc/gimple-fold.c | 50 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/fold-cstring.c | 44 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/fold-cvect.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr61762.c | 19 |
8 files changed, 211 insertions, 73 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a3715aefab8..268c40a6a5e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,23 @@ 2014-07-25 Richard Biener <rguenther@suse.de> + PR middle-end/61762 + PR middle-end/61894 + * fold-const.c (native_encode_int): Add and handle offset + parameter to do partial encodings of expr. + (native_encode_fixed): Likewise. + (native_encode_real): Likewise. + (native_encode_complex): Likewise. + (native_encode_vector): Likewise. + (native_encode_string): Likewise. + (native_encode_expr): Likewise. + * fold-const.c (native_encode_expr): Add offset parameter + defaulting to -1. + * gimple-fold.c (fold_string_cst_ctor_reference): Remove. + (fold_ctor_reference): Handle all reads from tcc_constant + ctors. + +2014-07-25 Richard Biener <rguenther@suse.de> + * tree-inline.c (estimate_move_cost): Mark speed_p argument as possibly unused. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index ff9e4048b6c..0999625dc28 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -7240,15 +7240,18 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type, upon failure. */ static int -native_encode_int (const_tree expr, unsigned char *ptr, int len) +native_encode_int (const_tree expr, unsigned char *ptr, int len, int off) { tree type = TREE_TYPE (expr); int total_bytes = GET_MODE_SIZE (TYPE_MODE (type)); int byte, offset, word, words; unsigned char value; - if (total_bytes > len) + if ((off == -1 && total_bytes > len) + || off >= total_bytes) return 0; + if (off == -1) + off = 0; words = total_bytes / UNITS_PER_WORD; for (byte = 0; byte < total_bytes; byte++) @@ -7271,9 +7274,11 @@ native_encode_int (const_tree expr, unsigned char *ptr, int len) } else offset = BYTES_BIG_ENDIAN ? (total_bytes - 1) - byte : byte; - ptr[offset] = value; + if (offset >= off + && offset - off < len) + ptr[offset - off] = value; } - return total_bytes; + return MIN (len, total_bytes - off); } @@ -7283,7 +7288,7 @@ native_encode_int (const_tree expr, unsigned char *ptr, int len) upon failure. */ static int -native_encode_fixed (const_tree expr, unsigned char *ptr, int len) +native_encode_fixed (const_tree expr, unsigned char *ptr, int len, int off) { tree type = TREE_TYPE (expr); enum machine_mode mode = TYPE_MODE (type); @@ -7303,7 +7308,7 @@ native_encode_fixed (const_tree expr, unsigned char *ptr, int len) value = TREE_FIXED_CST (expr); i_value = double_int_to_tree (i_type, value.data); - return native_encode_int (i_value, ptr, len); + return native_encode_int (i_value, ptr, len, off); } @@ -7313,7 +7318,7 @@ native_encode_fixed (const_tree expr, unsigned char *ptr, int len) upon failure. */ static int -native_encode_real (const_tree expr, unsigned char *ptr, int len) +native_encode_real (const_tree expr, unsigned char *ptr, int len, int off) { tree type = TREE_TYPE (expr); int total_bytes = GET_MODE_SIZE (TYPE_MODE (type)); @@ -7325,8 +7330,11 @@ native_encode_real (const_tree expr, unsigned char *ptr, int len) up to 192 bits. */ long tmp[6]; - if (total_bytes > len) + if ((off == -1 && total_bytes > len) + || off >= total_bytes) return 0; + if (off == -1) + off = 0; words = (32 / BITS_PER_UNIT) / UNITS_PER_WORD; real_to_target (tmp, TREE_REAL_CST_PTR (expr), TYPE_MODE (type)); @@ -7350,9 +7358,12 @@ native_encode_real (const_tree expr, unsigned char *ptr, int len) } else offset = BYTES_BIG_ENDIAN ? 3 - byte : byte; - ptr[offset + ((bitpos / BITS_PER_UNIT) & ~3)] = value; + offset = offset + ((bitpos / BITS_PER_UNIT) & ~3); + if (offset >= off + && offset - off < len) + ptr[offset - off] = value; } - return total_bytes; + return MIN (len, total_bytes - off); } /* Subroutine of native_encode_expr. Encode the COMPLEX_CST @@ -7361,18 +7372,22 @@ native_encode_real (const_tree expr, unsigned char *ptr, int len) upon failure. */ static int -native_encode_complex (const_tree expr, unsigned char *ptr, int len) +native_encode_complex (const_tree expr, unsigned char *ptr, int len, int off) { int rsize, isize; tree part; part = TREE_REALPART (expr); - rsize = native_encode_expr (part, ptr, len); - if (rsize == 0) + rsize = native_encode_expr (part, ptr, len, off); + if (off == -1 + && rsize == 0) return 0; part = TREE_IMAGPART (expr); - isize = native_encode_expr (part, ptr+rsize, len-rsize); - if (isize != rsize) + if (off != -1) + off = MAX (0, off - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (part)))); + isize = native_encode_expr (part, ptr+rsize, len-rsize, off); + if (off == -1 + && isize != rsize) return 0; return rsize + isize; } @@ -7384,7 +7399,7 @@ native_encode_complex (const_tree expr, unsigned char *ptr, int len) upon failure. */ static int -native_encode_vector (const_tree expr, unsigned char *ptr, int len) +native_encode_vector (const_tree expr, unsigned char *ptr, int len, int off) { unsigned i, count; int size, offset; @@ -7396,10 +7411,21 @@ native_encode_vector (const_tree expr, unsigned char *ptr, int len) size = GET_MODE_SIZE (TYPE_MODE (itype)); for (i = 0; i < count; i++) { + if (off >= size) + { + off -= size; + continue; + } elem = VECTOR_CST_ELT (expr, i); - if (native_encode_expr (elem, ptr+offset, len-offset) != size) + int res = native_encode_expr (elem, ptr+offset, len-offset, off); + if ((off == -1 && res != size) + || res == 0) return 0; - offset += size; + offset += res; + if (offset >= len) + return offset; + if (off != -1) + off = 0; } return offset; } @@ -7411,7 +7437,7 @@ native_encode_vector (const_tree expr, unsigned char *ptr, int len) upon failure. */ static int -native_encode_string (const_tree expr, unsigned char *ptr, int len) +native_encode_string (const_tree expr, unsigned char *ptr, int len, int off) { tree type = TREE_TYPE (expr); HOST_WIDE_INT total_bytes; @@ -7422,47 +7448,56 @@ native_encode_string (const_tree expr, unsigned char *ptr, int len) || !tree_fits_shwi_p (TYPE_SIZE_UNIT (type))) return 0; total_bytes = tree_to_shwi (TYPE_SIZE_UNIT (type)); - if (total_bytes > len) + if ((off == -1 && total_bytes > len) + || off >= total_bytes) return 0; - if (TREE_STRING_LENGTH (expr) < total_bytes) + if (off == -1) + off = 0; + if (TREE_STRING_LENGTH (expr) - off < MIN (total_bytes, len)) { - memcpy (ptr, TREE_STRING_POINTER (expr), TREE_STRING_LENGTH (expr)); - memset (ptr + TREE_STRING_LENGTH (expr), 0, - total_bytes - TREE_STRING_LENGTH (expr)); + int written = 0; + if (off < TREE_STRING_LENGTH (expr)) + { + written = MIN (len, TREE_STRING_LENGTH (expr) - off); + memcpy (ptr, TREE_STRING_POINTER (expr) + off, written); + } + memset (ptr + written, 0, + MIN (total_bytes - written, len - written)); } else - memcpy (ptr, TREE_STRING_POINTER (expr), total_bytes); - return total_bytes; + memcpy (ptr, TREE_STRING_POINTER (expr) + off, MIN (total_bytes, len)); + return MIN (total_bytes - off, len); } /* Subroutine of fold_view_convert_expr. Encode the INTEGER_CST, REAL_CST, COMPLEX_CST or VECTOR_CST specified by EXPR into the - buffer PTR of length LEN bytes. Return the number of bytes - placed in the buffer, or zero upon failure. */ + buffer PTR of length LEN bytes. If OFF is not -1 then start + the encoding at byte offset OFF and encode at most LEN bytes. + Return the number of bytes placed in the buffer, or zero upon failure. */ int -native_encode_expr (const_tree expr, unsigned char *ptr, int len) +native_encode_expr (const_tree expr, unsigned char *ptr, int len, int off) { switch (TREE_CODE (expr)) { case INTEGER_CST: - return native_encode_int (expr, ptr, len); + return native_encode_int (expr, ptr, len, off); case REAL_CST: - return native_encode_real (expr, ptr, len); + return native_encode_real (expr, ptr, len, off); case FIXED_CST: - return native_encode_fixed (expr, ptr, len); + return native_encode_fixed (expr, ptr, len, off); case COMPLEX_CST: - return native_encode_complex (expr, ptr, len); + return native_encode_complex (expr, ptr, len, off); case VECTOR_CST: - return native_encode_vector (expr, ptr, len); + return native_encode_vector (expr, ptr, len, off); case STRING_CST: - return native_encode_string (expr, ptr, len); + return native_encode_string (expr, ptr, len, off); default: return 0; diff --git a/gcc/fold-const.h b/gcc/fold-const.h index 3b5fd8476d6..b440ca11881 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see extern int folding_initializer; /* Convert between trees and native memory representation. */ -extern int native_encode_expr (const_tree, unsigned char *, int); +extern int native_encode_expr (const_tree, unsigned char *, int, int off = -1); extern tree native_interpret_expr (tree, const unsigned char *, int); /* Fold constants as much as possible in an expression. diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 4e8de8235f8..747c0aa0b35 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2881,41 +2881,6 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset, } } -/* CTOR is STRING_CST. Fold reference of type TYPE and size SIZE - to the memory at bit OFFSET. - - We do only simple job of folding byte accesses. */ - -static tree -fold_string_cst_ctor_reference (tree type, tree ctor, - unsigned HOST_WIDE_INT offset, - unsigned HOST_WIDE_INT size) -{ - if (INTEGRAL_TYPE_P (type) - && (TYPE_MODE (type) - == TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor)))) - && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor)))) - == MODE_INT) - && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (ctor)))) == 1 - && size == BITS_PER_UNIT - && !(offset % BITS_PER_UNIT)) - { - offset /= BITS_PER_UNIT; - if (offset < (unsigned HOST_WIDE_INT) TREE_STRING_LENGTH (ctor)) - return build_int_cst_type (type, (TREE_STRING_POINTER (ctor) - [offset])); - /* Folding - const char a[20]="hello"; - return a[10]; - - might lead to offset greater than string length. In this case we - know value is either initialized to 0 or out of bounds. Return 0 - in both cases. */ - return build_zero_cst (type); - } - return NULL_TREE; -} - /* CTOR is CONSTRUCTOR of an array type. Fold reference of type TYPE and size SIZE to the memory at bit OFFSET. */ @@ -3107,8 +3072,19 @@ fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset, STRIP_NOPS (ret); return ret; } - if (TREE_CODE (ctor) == STRING_CST) - return fold_string_cst_ctor_reference (type, ctor, offset, size); + /* For constants and byte-aligned/sized reads try to go through + native_encode/interpret. */ + if (CONSTANT_CLASS_P (ctor) + && BITS_PER_UNIT == 8 + && offset % BITS_PER_UNIT == 0 + && size % BITS_PER_UNIT == 0 + && size <= MAX_BITSIZE_MODE_ANY_MODE) + { + unsigned char buf[MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT]; + if (native_encode_expr (ctor, buf, size / BITS_PER_UNIT, + offset / BITS_PER_UNIT) > 0) + return native_interpret_expr (type, buf, size / BITS_PER_UNIT); + } if (TREE_CODE (ctor) == CONSTRUCTOR) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 17daa074a94..72ba8a7a8a8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2014-07-25 Richard Biener <rguenther@suse.de> + + PR middle-end/61762 + PR middle-end/61894 + * gcc.dg/pr61762.c: New testcase. + * gcc.dg/fold-cstring.c: Likewise. + * gcc.dg/fold-cvect.c: Likewise. + 2014-07-24 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> * gcc.target/powerpc/ppc64-abi-warn-3.c: New test. diff --git a/gcc/testsuite/gcc.dg/fold-cstring.c b/gcc/testsuite/gcc.dg/fold-cstring.c new file mode 100644 index 00000000000..f92b120b3b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-cstring.c @@ -0,0 +1,44 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +/* The following are testcases for native_interpret_int, + native_interpret_complex and native_interpret_vector decoding + pieces of a string constant encoded by native_encode_string. */ + +extern void abort (void); + +/* We should fold all reads from xconstant and eliminate it, removing + the reference to blah which cannot be resolved at link time. */ +extern int blah; + +static const struct { + int *y; + const char x[32] __attribute__((aligned(32))); +} xconstant = { &blah, "01234567899876543210123456789000" }; + +typedef int v4si __attribute__((vector_size(16))); + +int main() +{ + if (sizeof (int) != 4) + return 0; + if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + { + if (*(int *)&xconstant.x[4] != 0x34353637) + abort (); + if ((*(v4si *)&xconstant.x[16])[1] != 0x31323334) + abort (); + if (__imag (*(_Complex int *)&xconstant.x[8]) != 0x37363534) + abort (); + } + else if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + { + if (*(int *)&xconstant.x[4] != 0x37363534) + abort (); + if ((*(v4si *)&xconstant.x[16])[1] != 0x34333231) + abort (); + if (__imag (*(_Complex int *)&xconstant.x[8]) != 0x34353637) + abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/fold-cvect.c b/gcc/testsuite/gcc.dg/fold-cvect.c new file mode 100644 index 00000000000..8687f8db2ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-cvect.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +extern void abort (void); + +/* We should fold all reads from xconstant and eliminate it, removing + the reference to blah which cannot be resolved at link time. */ +extern int blah; + +typedef int v4si __attribute__((vector_size(16))); + +static const struct { + int *y; + const v4si x[2] __attribute__((aligned(32))); +} xconstant = { &blah, { { 0, 1, 2, 3 }, { 2, 3, 4, 5 } } }; + +int main() +{ + if (sizeof (int) != 4) + return 0; + if (*(int *)&xconstant.x[0][0] != 0) + abort (); + if (*(int *)&xconstant.x[0][1] != 1) + abort (); + if (*(int *)&xconstant.x[0][2] != 2) + abort (); + if (*(int *)&xconstant.x[0][3] != 3) + abort (); + if (*(int *)&xconstant.x[1][0] != 2) + abort (); + if (*(int *)&xconstant.x[1][1] != 3) + abort (); + if (*(int *)&xconstant.x[1][2] != 4) + abort (); + if (*(int *)&xconstant.x[1][3] != 5) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr61762.c b/gcc/testsuite/gcc.dg/pr61762.c new file mode 100644 index 00000000000..5abe5347e4a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr61762.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-release_ssa" } */ + +unsigned int f() +{ + static const char string[] = "Private"; + + unsigned int priv; + __builtin_memcpy(&priv, &string[0], sizeof(priv)); + return priv; +} + +/* We should have removed the static string and simplified the + memcpy to a store from an integer constant. CCP + already performs the simplification but only after release_ssa + the unused local static is removed. */ + +/* { dg-final { scan-tree-dump-not "Private" "release_ssa" } } */ +/* { dg-final { cleanup-tree-dump "release_ssa" } } */ |