On Fri, 11 Jul 2014, Richard Biener wrote: > On Fri, 11 Jul 2014, Jakub Jelinek wrote: > > > On Fri, Jul 11, 2014 at 10:00:01AM +0200, Richard Biener wrote: > > > I started with adding an optional arg to native_encode_expr but then > > > figured that all the current workers return failure if the entire > > > expr doesn't fit within 'len'. But what I want is a native_encode_expr > > > > That is because the functions were written for VIEW_CONVERT_EXPR folding > > where it is expected that both the types are the same size, and it doesn't > > make sense to spend too much time on large stuff that doesn't fit into > > the fold_view_convert_expr's fixed size buffer. Now, for your case > > the sizes aren't the same and thus partial data is just fine, because > > what native_interpret_expr will do is small fixed size. > > So I don't see a problem with not returning NULL and instead handling the > > partial store into buffer if you ask for it through optional argument > > (doing it always would be fine for fold_view_convert_expr assuming nobody > > feeds us different sized argument vs. VCE type, but e.g. > > tree-loop-distribution.c certainly appreciates if we return NULL for large > > things, because if it had just partial buffer, it would not be able to > > verify what it is looking for). > > Yeah, if you pass 'offset' then 'len' suddenly changes semantics > from specifying the buffer size to specifying the desired amount > of encoded data ... (which the present interface computes for you, > the caller doesn't even need to know how large it is). > > The question is also if I ask native_encode_expr to produce > data for [offset, offset + len] but the object only contains > part of it - thus the tail is 'undefined' - do we want to fail > or simply feed (undefined) "garbage" to the following > native_interpret_expr? (yes, native_encode_expr will of course > return sth < len in this case)
Like the following (completely untested - lacks handling of len < total_bytes - off as I just figured out). If off is -1 then it should behave as the current interface, else we encode the part [off, off + MIN (len, total_bytes)] and return MIN (len, total_bytes). Ah, a guard against off >= total_bytes is also missing. I wonder if it would be ok to start with gcc_assert (off == -1) in all but native_encode_string. Does the interface look sane? Thanks, Richard. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 212449) +++ gcc/fold-const.c (working copy) @@ -7239,15 +7239,17 @@ fold_plusminus_mult_expr (location_t loc 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) return 0; + if (off == -1) + off = 0; words = total_bytes / UNITS_PER_WORD; for (byte = 0; byte < total_bytes; byte++) @@ -7270,9 +7272,10 @@ native_encode_int (const_tree expr, unsi } else offset = BYTES_BIG_ENDIAN ? (total_bytes - 1) - byte : byte; - ptr[offset] = value; + if (offset >= off) + ptr[offset - off] = value; } - return total_bytes; + return total_bytes - off; } @@ -7282,7 +7285,7 @@ native_encode_int (const_tree expr, unsi 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); @@ -7290,7 +7293,8 @@ native_encode_fixed (const_tree expr, un FIXED_VALUE_TYPE value; tree i_value, i_type; - if (total_bytes * BITS_PER_UNIT > HOST_BITS_PER_DOUBLE_INT) + if (off == -1 + && total_bytes * BITS_PER_UNIT > HOST_BITS_PER_DOUBLE_INT) return 0; i_type = lang_hooks.types.type_for_size (GET_MODE_BITSIZE (mode), 1); @@ -7302,7 +7306,7 @@ native_encode_fixed (const_tree expr, un 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); } @@ -7312,7 +7316,7 @@ native_encode_fixed (const_tree expr, un 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)); @@ -7324,8 +7328,11 @@ native_encode_real (const_tree expr, uns up to 192 bits. */ long tmp[6]; - if (total_bytes > len) + if (off == -1 + && total_bytes > len) 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)); @@ -7349,9 +7356,11 @@ native_encode_real (const_tree expr, uns } 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) + ptr[offset - off] = value; } - return total_bytes; + return total_bytes - off; } /* Subroutine of native_encode_expr. Encode the COMPLEX_CST @@ -7360,18 +7369,21 @@ native_encode_real (const_tree expr, uns 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); + rsize = native_encode_expr (part, ptr, len, off); if (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 - rsize); + isize = native_encode_expr (part, ptr+rsize, len-rsize, off); + if (off == -1 + && isize != rsize) return 0; return rsize + isize; } @@ -7383,7 +7395,7 @@ native_encode_complex (const_tree expr, 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,9 +7408,13 @@ native_encode_vector (const_tree expr, u for (i = 0; i < count; i++) { 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) return 0; - offset += size; + offset += res; + if (off != -1) + off = MAX (0, off - res); } return offset; } @@ -7410,7 +7426,7 @@ native_encode_vector (const_tree expr, u 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; @@ -7421,17 +7437,21 @@ native_encode_string (const_tree expr, u || !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) return 0; + if (off == -1) + off = 0; if (TREE_STRING_LENGTH (expr) < total_bytes) { - memcpy (ptr, TREE_STRING_POINTER (expr), TREE_STRING_LENGTH (expr)); - memset (ptr + TREE_STRING_LENGTH (expr), 0, - total_bytes - TREE_STRING_LENGTH (expr)); + memcpy (ptr, TREE_STRING_POINTER (expr) + off, + TREE_STRING_LENGTH (expr) - off); + memset (ptr + TREE_STRING_LENGTH (expr) - off, 0, + MIN (total_bytes, len) - TREE_STRING_LENGTH (expr) + off); } 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); } @@ -7441,27 +7461,27 @@ native_encode_string (const_tree expr, u 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; Index: gcc/fold-const.h =================================================================== --- gcc/fold-const.h (revision 212449) +++ gcc/fold-const.h (working copy) @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. 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.