aboutsummaryrefslogtreecommitdiff
path: root/gcc/double-int.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/double-int.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/double-int.c')
-rw-r--r--gcc/double-int.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/gcc/double-int.c b/gcc/double-int.c
index a02a6aa..918ce22 100644
--- a/gcc/double-int.c
+++ b/gcc/double-int.c
@@ -641,6 +641,54 @@ div_and_round_double (unsigned code, int uns,
return overflow;
}
+
+/* Construct from a buffer of length LEN. BUFFER will be read according
+ to byte endianess and word endianess. Only the lower LEN bytes
+ of the result are set; the remaining high bytes are cleared. */
+
+double_int
+double_int::from_buffer (const unsigned char *buffer, int len)
+{
+ double_int result = double_int_zero;
+ int words = len / UNITS_PER_WORD;
+
+ gcc_assert (len * BITS_PER_UNIT <= HOST_BITS_PER_DOUBLE_INT);
+
+ for (int byte = 0; byte < len; byte++)
+ {
+ int offset;
+ int bitpos = byte * BITS_PER_UNIT;
+ unsigned HOST_WIDE_INT value;
+
+ if (len > UNITS_PER_WORD)
+ {
+ int 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 ? (len - 1) - byte : byte;
+
+ value = (unsigned HOST_WIDE_INT) buffer[offset];
+
+ if (bitpos < HOST_BITS_PER_WIDE_INT)
+ result.low |= value << bitpos;
+ else
+ result.high |= value << (bitpos - HOST_BITS_PER_WIDE_INT);
+ }
+
+ return result;
+}
+
+
/* Returns mask for PREC bits. */
double_int