aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2013-01-30 11:04:30 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2013-01-30 11:04:30 +0000
commitcc06c01d0a29c6e1466feba98d8ae3bf20193822 (patch)
tree7cbebdbd492e700058cfc647470eb384b37f121e /gcc/fold-const.c
parentd394a308e34df7dfe56e1b3995a2622e1ed19068 (diff)
downloadgcc-cc06c01d0a29c6e1466feba98d8ae3bf20193822.zip
gcc-cc06c01d0a29c6e1466feba98d8ae3bf20193822.tar.gz
gcc-cc06c01d0a29c6e1466feba98d8ae3bf20193822.tar.bz2
re PR tree-optimization/56064 (Optimize VIEW_CONVERT_EXPR with FIXED_CST)
gcc/ PR tree-optimization/56064 * fixed-value.c (fixed_from_double_int): New function. * fixed-value.h (fixed_from_double_int): New prototype. (const_fixed_from_double_int): New static inline function. * fold-const.c (native_interpret_fixed): New static function. (native_interpret_expr) <FIXED_POINT_TYPE>: Use it. (can_native_interpret_type_p) <FIXED_POINT_TYPE>: Return true. (native_encode_fixed): New static function. (native_encode_expr) <FIXED_CST>: Use it. (native_interpret_int): Move double_int worker code to... * double-int.c (double_int::from_buffer): ...this new static method. * double-int.h (double_int::from_buffer): Prototype it. gcc/testsuite/ PR tree-optimization/56064 * gcc.dg/fixed-point/view-convert.c: New test. From-SVN: r195574
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c92
1 files changed, 61 insertions, 31 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index efad9a9..855f08f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7200,6 +7200,36 @@ native_encode_int (const_tree expr, unsigned char *ptr, int len)
}
+/* Subroutine of native_encode_expr. Encode the FIXED_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. */
+
+static int
+native_encode_fixed (const_tree expr, unsigned char *ptr, int len)
+{
+ tree type = TREE_TYPE (expr);
+ enum machine_mode mode = TYPE_MODE (type);
+ int total_bytes = GET_MODE_SIZE (mode);
+ FIXED_VALUE_TYPE value;
+ tree i_value, i_type;
+
+ if (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);
+
+ if (NULL_TREE == i_type
+ || TYPE_PRECISION (i_type) != total_bytes)
+ return 0;
+
+ value = TREE_FIXED_CST (expr);
+ i_value = double_int_to_tree (i_type, value.data);
+
+ return native_encode_int (i_value, ptr, len);
+}
+
+
/* Subroutine of native_encode_expr. Encode the REAL_CST
specified by EXPR into the buffer PTR of length LEN bytes.
Return the number of bytes placed in the buffer, or zero
@@ -7345,6 +7375,9 @@ native_encode_expr (const_tree expr, unsigned char *ptr, int len)
case REAL_CST:
return native_encode_real (expr, ptr, len);
+ case FIXED_CST:
+ return native_encode_fixed (expr, ptr, len);
+
case COMPLEX_CST:
return native_encode_complex (expr, ptr, len);
@@ -7368,44 +7401,37 @@ static tree
native_interpret_int (tree type, const unsigned char *ptr, int len)
{
int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
- int byte, offset, word, words;
- unsigned char value;
double_int result;
- if (total_bytes > len)
- return NULL_TREE;
- if (total_bytes * BITS_PER_UNIT > HOST_BITS_PER_DOUBLE_INT)
+ if (total_bytes > len
+ || total_bytes * BITS_PER_UNIT > HOST_BITS_PER_DOUBLE_INT)
return NULL_TREE;
- result = double_int_zero;
- words = total_bytes / UNITS_PER_WORD;
+ result = double_int::from_buffer (ptr, total_bytes);
- for (byte = 0; byte < total_bytes; byte++)
- {
- int bitpos = byte * BITS_PER_UNIT;
- if (total_bytes > UNITS_PER_WORD)
- {
- word = byte / UNITS_PER_WORD;
- if (WORDS_BIG_ENDIAN)
- word = (words - 1) - word;
- offset = word * UNITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
- offset += (UNITS_PER_WORD - 1) - (byte % UNITS_PER_WORD);
- else
- offset += byte % UNITS_PER_WORD;
- }
- else
- offset = BYTES_BIG_ENDIAN ? (total_bytes - 1) - byte : byte;
- value = ptr[offset];
+ return double_int_to_tree (type, result);
+}
- if (bitpos < HOST_BITS_PER_WIDE_INT)
- result.low |= (unsigned HOST_WIDE_INT) value << bitpos;
- else
- result.high |= (unsigned HOST_WIDE_INT) value
- << (bitpos - HOST_BITS_PER_WIDE_INT);
- }
- return double_int_to_tree (type, result);
+/* Subroutine of native_interpret_expr. Interpret the contents of
+ the buffer PTR of length LEN as a FIXED_CST of type TYPE.
+ If the buffer cannot be interpreted, return NULL_TREE. */
+
+static tree
+native_interpret_fixed (tree type, const unsigned char *ptr, int len)
+{
+ int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
+ double_int result;
+ FIXED_VALUE_TYPE fixed_value;
+
+ if (total_bytes > len
+ || total_bytes * BITS_PER_UNIT > HOST_BITS_PER_DOUBLE_INT)
+ return NULL_TREE;
+
+ result = double_int::from_buffer (ptr, total_bytes);
+ fixed_value = fixed_from_double_int (result, TYPE_MODE (type));
+
+ return build_fixed (type, fixed_value);
}
@@ -7533,6 +7559,9 @@ native_interpret_expr (tree type, const unsigned char *ptr, int len)
case REAL_TYPE:
return native_interpret_real (type, ptr, len);
+ case FIXED_POINT_TYPE:
+ return native_interpret_fixed (type, ptr, len);
+
case COMPLEX_TYPE:
return native_interpret_complex (type, ptr, len);
@@ -7557,6 +7586,7 @@ can_native_interpret_type_p (tree type)
case BOOLEAN_TYPE:
case POINTER_TYPE:
case REFERENCE_TYPE:
+ case FIXED_POINT_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE: