* [Patch] PR56064: Fold VIEW_CONVERT_EXPR with FIXED_CST
@ 2013-01-21 13:29 Georg-Johann Lay
2013-01-29 11:27 ` Richard Biener
0 siblings, 1 reply; 4+ messages in thread
From: Georg-Johann Lay @ 2013-01-21 13:29 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1348 bytes --]
This is tentative patch as discussed in
http://gcc.gnu.org/ml/gcc/2013-01/msg00187.html
fold-const.c gets 2 new function native_encode_fixed and
native_interpret_fixed. Code common with the integer case is factored out and
moved to the new constructor-like function double_int::from_buffer.
The code bootstraps fine on x86-linux-gnu and I have test coverage from
avr-unknown-none.
Ok to apply?
There are less intrusive solutions that only handle the int <-> fixed cases,
for example fold-const.c:fold_view_convert_expr() could test for these cases
and use double_int directly without serializing / deserializing through a
memory buffer.
Johann
PR tree-optimization/56064
* fixed-value.c (const_fixed_from_double_int): New function.
* fixed-value.h (const_fixed_from_double_int): New prototype.
* 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.
testsuite/
PR tree-optimization/56064
* gcc.dg/fixed-point/view-convert.c: New test.
[-- Attachment #2: viewconv-fixed.diff --]
[-- Type: text/x-patch, Size: 11111 bytes --]
Index: fixed-value.c
===================================================================
--- fixed-value.c (revision 195301)
+++ fixed-value.c (working copy)
@@ -81,6 +81,24 @@ check_real_for_fixed_mode (REAL_VALUE_TY
return FIXED_OK;
}
+
+/* Construct a CONST_FIXED from a bit payload and machine mode MODE.
+ The bits in PAYLOAD are used verbatim. */
+
+FIXED_VALUE_TYPE
+const_fixed_from_double_int (double_int payload, enum machine_mode mode)
+{
+ FIXED_VALUE_TYPE value;
+
+ gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_DOUBLE_INT);
+
+ value.data = payload;
+ value.mode = mode;
+
+ return value;
+}
+
+
/* Initialize from a decimal or hexadecimal string. */
void
Index: fixed-value.h
===================================================================
--- fixed-value.h (revision 195301)
+++ fixed-value.h (working copy)
@@ -49,6 +49,11 @@ extern FIXED_VALUE_TYPE fconst1[MAX_FCON
const_fixed_from_fixed_value (r, m)
extern rtx const_fixed_from_fixed_value (FIXED_VALUE_TYPE, enum machine_mode);
+/* Construct a CONST_FIXED from a bit payload and machine mode MODE.
+ The bits in PAYLOAD are used verbatim. */
+extern FIXED_VALUE_TYPE const_fixed_from_double_int (double_int,
+ enum machine_mode);
+
/* Initialize from a decimal or hexadecimal string. */
extern void fixed_from_string (FIXED_VALUE_TYPE *, const char *,
enum machine_mode);
Index: fold-const.c
===================================================================
--- fold-const.c (revision 195301)
+++ fold-const.c (working copy)
@@ -7200,6 +7200,36 @@ native_encode_int (const_tree expr, unsi
}
+/* 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, uns
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 = const_fixed_from_double_int (result, TYPE_MODE (type));
+
+ return build_fixed (type, fixed_value);
}
@@ -7533,6 +7559,9 @@ native_interpret_expr (tree type, const
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:
Index: double-int.c
===================================================================
--- double-int.c (revision 195301)
+++ double-int.c (working copy)
@@ -641,6 +641,54 @@ div_and_round_double (unsigned code, int
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
Index: double-int.h
===================================================================
--- double-int.h (revision 195301)
+++ double-int.h (working copy)
@@ -59,6 +59,10 @@ struct double_int
static double_int from_shwi (HOST_WIDE_INT cst);
static double_int from_pair (HOST_WIDE_INT high, unsigned HOST_WIDE_INT low);
+ /* Construct from a fuffer of length LEN. BUFFER will be read according
+ to byte endianess and word endianess. */
+ static double_int from_buffer (const unsigned char *buffer, int len);
+
/* No copy assignment operator or destructor to keep the type a POD. */
/* There are some special value-creation static member functions. */
Index: testsuite/gcc.dg/fixed-point/view-convert.c
===================================================================
--- testsuite/gcc.dg/fixed-point/view-convert.c (revision 0)
+++ testsuite/gcc.dg/fixed-point/view-convert.c (revision 0)
@@ -0,0 +1,122 @@
+/* PR tree-optimization/56064 */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -O2 -fno-builtin-memcpy" } */
+
+extern void abort (void);
+extern void *memcpy (void*, const void*, __SIZE_TYPE__);
+
+#define f_pun_i(F, I, VAL) \
+ { \
+ I i1 = VAL; \
+ I i2 = VAL; \
+ F q1, q2; \
+ memcpy (&q1, &i1, sizeof (I)); \
+ __builtin_memcpy (&q2, &i2, sizeof (I)); \
+ if (q1 != q2) \
+ abort(); \
+ }
+
+#define i_pun_f(I, F, VAL) \
+ { \
+ F q1 = VAL; \
+ F q2 = VAL; \
+ I i1, i2; \
+ memcpy (&i1, &q1, sizeof (I)); \
+ __builtin_memcpy (&i2, &q2, sizeof (I)); \
+ if (i1 != i2) \
+ abort(); \
+ }
+
+
+void __attribute__((noinline))
+test8 (void)
+{
+#ifdef __INT8_TYPE__
+ if (sizeof (__INT8_TYPE__) == sizeof (short _Fract))
+ {
+#define TEST(X) f_pun_i (short _Fract, __INT8_TYPE__, __INT8_C (X))
+ TEST (123);
+ TEST (-123);
+#undef TEST
+
+#define TEST(X) i_pun_f (__INT8_TYPE__, short _Fract, X ## hr)
+ TEST (0.1234);
+ TEST (-0.987);
+#undef TEST
+ }
+#endif /* __INT8_TYPE__ */
+}
+
+
+void __attribute__((noinline))
+test16 (void)
+{
+#ifdef __INT16_TYPE__
+
+ if (sizeof (__INT16_TYPE__) == sizeof (_Fract))
+ {
+#define TEST(X) f_pun_i (_Fract, __INT16_TYPE__, __INT16_C (X))
+ TEST (0x4321);
+ TEST (-0x4321);
+ TEST (0x8000);
+#undef TEST
+
+#define TEST(X) i_pun_f (__INT16_TYPE__, _Fract, X ## r)
+ TEST (0.12345);
+ TEST (-0.98765);
+#undef TEST
+ }
+#endif /* __INT16_TYPE__ */
+}
+
+
+void __attribute__((noinline))
+test32 (void)
+{
+#ifdef __INT32_TYPE__
+ if (sizeof (__INT32_TYPE__) == sizeof (_Accum))
+ {
+#define TEST(X) f_pun_i (_Accum, __INT32_TYPE__, __INT32_C (X))
+ TEST (0x76543219);
+ TEST (-0x76543219);
+ TEST (0x80000000);
+#undef TEST
+
+#define TEST(X) i_pun_f (__INT32_TYPE__, _Accum, X ## k)
+ TEST (123.456789);
+ TEST (-123.456789);
+#undef TEST
+ }
+#endif /* __INT32_TYPE__ */
+}
+
+
+void __attribute__((noinline))
+test64 (void)
+{
+#ifdef __INT64_TYPE__
+ if (sizeof (__INT64_TYPE__) == sizeof (long _Accum))
+ {
+#define TEST(X) f_pun_i (long _Accum, __INT64_TYPE__, __INT64_C (X))
+ TEST (0x12345678abcdef01);
+ TEST (-0x12345678abcdef01);
+ TEST (0x8000000000000000);
+#undef TEST
+
+#define TEST(X) i_pun_f (__INT64_TYPE__, long _Accum, X ## lk)
+ TEST (123.456789);
+ TEST (-123.456789);
+#undef TEST
+ }
+#endif /* __INT64_TYPE__ */
+}
+
+int main()
+{
+ test8();
+ test16();
+ test32();
+ test64();
+
+ return 0;
+}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Patch] PR56064: Fold VIEW_CONVERT_EXPR with FIXED_CST
2013-01-21 13:29 [Patch] PR56064: Fold VIEW_CONVERT_EXPR with FIXED_CST Georg-Johann Lay
@ 2013-01-29 11:27 ` Richard Biener
2013-01-29 20:00 ` [Patch] PR56064: Fold VIEW_CONVERT_EXPR with FIXED_CST, Take #2 Georg-Johann Lay
0 siblings, 1 reply; 4+ messages in thread
From: Richard Biener @ 2013-01-29 11:27 UTC (permalink / raw)
To: Georg-Johann Lay; +Cc: gcc-patches
On Mon, Jan 21, 2013 at 2:28 PM, Georg-Johann Lay <avr@gjlay.de> wrote:
> This is tentative patch as discussed in
>
> http://gcc.gnu.org/ml/gcc/2013-01/msg00187.html
>
> fold-const.c gets 2 new function native_encode_fixed and
> native_interpret_fixed. Code common with the integer case is factored out and
> moved to the new constructor-like function double_int::from_buffer.
>
> The code bootstraps fine on x86-linux-gnu and I have test coverage from
> avr-unknown-none.
>
> Ok to apply?
Ok.
Thanks,
Richard.
> There are less intrusive solutions that only handle the int <-> fixed cases,
> for example fold-const.c:fold_view_convert_expr() could test for these cases
> and use double_int directly without serializing / deserializing through a
> memory buffer.
>
> Johann
>
>
> PR tree-optimization/56064
> * fixed-value.c (const_fixed_from_double_int): New function.
> * fixed-value.h (const_fixed_from_double_int): New prototype.
> * 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.
>
> testsuite/
> PR tree-optimization/56064
> * gcc.dg/fixed-point/view-convert.c: New test.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Patch] PR56064: Fold VIEW_CONVERT_EXPR with FIXED_CST, Take #2
2013-01-29 11:27 ` Richard Biener
@ 2013-01-29 20:00 ` Georg-Johann Lay
2013-01-30 10:36 ` Richard Biener
0 siblings, 1 reply; 4+ messages in thread
From: Georg-Johann Lay @ 2013-01-29 20:00 UTC (permalink / raw)
To: Richard Biener; +Cc: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 2919 bytes --]
Richard Biener wrote:
> Georg-Johann Lay wrote:
>> This is tentative patch as discussed in
>>
>> http://gcc.gnu.org/ml/gcc/2013-01/msg00187.html
>>
>> fold-const.c gets 2 new function native_encode_fixed and
>> native_interpret_fixed. Code common with the integer case is factored out and
>> moved to the new constructor-like function double_int::from_buffer.
>>
>> The code bootstraps fine on x86-linux-gnu and I have test coverage from
>> avr-unknown-none.
>>
>> Ok to apply?
>
> Ok.
>
> Thanks,
> Richard.
Let me drop this, I don't like the name "const_fixed_from_double_int". It's
bad and I think "fixed_from_double_int" is better. Other constructor-like
functions for FIXED_VALUE_TYPE use fixed_from_* whereas const_fixed_* returns a
CONST_FIXED rtx.
This is less confusing and fits better the naming convention.
The new patch also adds const_fixed_from_double_int that actually returns a
CONST_FIXED rtx. It's unused, but I would use it in the avr back.
Okay with that rename? (Or, at your option, without const_fixed_from_double_int).
Johann
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.
testsuite/
PR tree-optimization/56064
* gcc.dg/fixed-point/view-convert.c: New test.
>
>> There are less intrusive solutions that only handle the int <-> fixed cases,
>> for example fold-const.c:fold_view_convert_expr() could test for these cases
>> and use double_int directly without serializing / deserializing through a
>> memory buffer.
>>
>> Johann
>>
>>
>> PR tree-optimization/56064
>> * fixed-value.c (const_fixed_from_double_int): New function.
>> * fixed-value.h (const_fixed_from_double_int): New prototype.
>> * 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.
>>
>> testsuite/
>> PR tree-optimization/56064
>> * gcc.dg/fixed-point/view-convert.c: New test.
>
[-- Attachment #2: viewconv-fixed-2.diff --]
[-- Type: text/x-patch, Size: 11464 bytes --]
Index: fixed-value.c
===================================================================
--- fixed-value.c (revision 195514)
+++ fixed-value.c (working copy)
@@ -81,6 +81,24 @@ check_real_for_fixed_mode (REAL_VALUE_TY
return FIXED_OK;
}
+
+/* Construct a CONST_FIXED from a bit payload and machine mode MODE.
+ The bits in PAYLOAD are used verbatim. */
+
+FIXED_VALUE_TYPE
+fixed_from_double_int (double_int payload, enum machine_mode mode)
+{
+ FIXED_VALUE_TYPE value;
+
+ gcc_assert (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_DOUBLE_INT);
+
+ value.data = payload;
+ value.mode = mode;
+
+ return value;
+}
+
+
/* Initialize from a decimal or hexadecimal string. */
void
Index: fixed-value.h
===================================================================
--- fixed-value.h (revision 195514)
+++ fixed-value.h (working copy)
@@ -49,6 +49,22 @@ extern FIXED_VALUE_TYPE fconst1[MAX_FCON
const_fixed_from_fixed_value (r, m)
extern rtx const_fixed_from_fixed_value (FIXED_VALUE_TYPE, enum machine_mode);
+/* Construct a FIXED_VALUE from a bit payload and machine mode MODE.
+ The bits in PAYLOAD are used verbatim. */
+extern FIXED_VALUE_TYPE fixed_from_double_int (double_int,
+ enum machine_mode);
+
+/* Return a CONST_FIXED from a bit payload and machine mode MODE.
+ The bits in PAYLOAD are used verbatim. */
+static inline rtx
+const_fixed_from_double_int (double_int payload,
+ enum machine_mode mode)
+{
+ return
+ const_fixed_from_fixed_value (fixed_from_double_int (payload, mode),
+ mode);
+}
+
/* Initialize from a decimal or hexadecimal string. */
extern void fixed_from_string (FIXED_VALUE_TYPE *, const char *,
enum machine_mode);
Index: fold-const.c
===================================================================
--- fold-const.c (revision 195514)
+++ fold-const.c (working copy)
@@ -7200,6 +7200,36 @@ native_encode_int (const_tree expr, unsi
}
+/* 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, uns
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
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:
Index: double-int.c
===================================================================
--- double-int.c (revision 195514)
+++ double-int.c (working copy)
@@ -641,6 +641,54 @@ div_and_round_double (unsigned code, int
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
Index: double-int.h
===================================================================
--- double-int.h (revision 195514)
+++ double-int.h (working copy)
@@ -59,6 +59,10 @@ struct double_int
static double_int from_shwi (HOST_WIDE_INT cst);
static double_int from_pair (HOST_WIDE_INT high, unsigned HOST_WIDE_INT low);
+ /* Construct from a fuffer of length LEN. BUFFER will be read according
+ to byte endianess and word endianess. */
+ static double_int from_buffer (const unsigned char *buffer, int len);
+
/* No copy assignment operator or destructor to keep the type a POD. */
/* There are some special value-creation static member functions. */
Index: testsuite/gcc.dg/fixed-point/view-convert.c
===================================================================
--- testsuite/gcc.dg/fixed-point/view-convert.c (revision 0)
+++ testsuite/gcc.dg/fixed-point/view-convert.c (revision 0)
@@ -0,0 +1,122 @@
+/* PR tree-optimization/56064 */
+/* { dg-do run } */
+/* { dg-options "-std=gnu99 -O2 -fno-builtin-memcpy" } */
+
+extern void abort (void);
+extern void *memcpy (void*, const void*, __SIZE_TYPE__);
+
+#define f_pun_i(F, I, VAL) \
+ { \
+ I i1 = VAL; \
+ I i2 = VAL; \
+ F q1, q2; \
+ memcpy (&q1, &i1, sizeof (I)); \
+ __builtin_memcpy (&q2, &i2, sizeof (I)); \
+ if (q1 != q2) \
+ abort(); \
+ }
+
+#define i_pun_f(I, F, VAL) \
+ { \
+ F q1 = VAL; \
+ F q2 = VAL; \
+ I i1, i2; \
+ memcpy (&i1, &q1, sizeof (I)); \
+ __builtin_memcpy (&i2, &q2, sizeof (I)); \
+ if (i1 != i2) \
+ abort(); \
+ }
+
+
+void __attribute__((noinline))
+test8 (void)
+{
+#ifdef __INT8_TYPE__
+ if (sizeof (__INT8_TYPE__) == sizeof (short _Fract))
+ {
+#define TEST(X) f_pun_i (short _Fract, __INT8_TYPE__, __INT8_C (X))
+ TEST (123);
+ TEST (-123);
+#undef TEST
+
+#define TEST(X) i_pun_f (__INT8_TYPE__, short _Fract, X ## hr)
+ TEST (0.1234);
+ TEST (-0.987);
+#undef TEST
+ }
+#endif /* __INT8_TYPE__ */
+}
+
+
+void __attribute__((noinline))
+test16 (void)
+{
+#ifdef __INT16_TYPE__
+
+ if (sizeof (__INT16_TYPE__) == sizeof (_Fract))
+ {
+#define TEST(X) f_pun_i (_Fract, __INT16_TYPE__, __INT16_C (X))
+ TEST (0x4321);
+ TEST (-0x4321);
+ TEST (0x8000);
+#undef TEST
+
+#define TEST(X) i_pun_f (__INT16_TYPE__, _Fract, X ## r)
+ TEST (0.12345);
+ TEST (-0.98765);
+#undef TEST
+ }
+#endif /* __INT16_TYPE__ */
+}
+
+
+void __attribute__((noinline))
+test32 (void)
+{
+#ifdef __INT32_TYPE__
+ if (sizeof (__INT32_TYPE__) == sizeof (_Accum))
+ {
+#define TEST(X) f_pun_i (_Accum, __INT32_TYPE__, __INT32_C (X))
+ TEST (0x76543219);
+ TEST (-0x76543219);
+ TEST (0x80000000);
+#undef TEST
+
+#define TEST(X) i_pun_f (__INT32_TYPE__, _Accum, X ## k)
+ TEST (123.456789);
+ TEST (-123.456789);
+#undef TEST
+ }
+#endif /* __INT32_TYPE__ */
+}
+
+
+void __attribute__((noinline))
+test64 (void)
+{
+#ifdef __INT64_TYPE__
+ if (sizeof (__INT64_TYPE__) == sizeof (long _Accum))
+ {
+#define TEST(X) f_pun_i (long _Accum, __INT64_TYPE__, __INT64_C (X))
+ TEST (0x12345678abcdef01);
+ TEST (-0x12345678abcdef01);
+ TEST (0x8000000000000000);
+#undef TEST
+
+#define TEST(X) i_pun_f (__INT64_TYPE__, long _Accum, X ## lk)
+ TEST (123.456789);
+ TEST (-123.456789);
+#undef TEST
+ }
+#endif /* __INT64_TYPE__ */
+}
+
+int main()
+{
+ test8();
+ test16();
+ test32();
+ test64();
+
+ return 0;
+}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Patch] PR56064: Fold VIEW_CONVERT_EXPR with FIXED_CST, Take #2
2013-01-29 20:00 ` [Patch] PR56064: Fold VIEW_CONVERT_EXPR with FIXED_CST, Take #2 Georg-Johann Lay
@ 2013-01-30 10:36 ` Richard Biener
0 siblings, 0 replies; 4+ messages in thread
From: Richard Biener @ 2013-01-30 10:36 UTC (permalink / raw)
To: Georg-Johann Lay; +Cc: gcc-patches
On Tue, Jan 29, 2013 at 9:00 PM, Georg-Johann Lay <avr@gjlay.de> wrote:
> Richard Biener wrote:
>> Georg-Johann Lay wrote:
>>> This is tentative patch as discussed in
>>>
>>> http://gcc.gnu.org/ml/gcc/2013-01/msg00187.html
>>>
>>> fold-const.c gets 2 new function native_encode_fixed and
>>> native_interpret_fixed. Code common with the integer case is factored out and
>>> moved to the new constructor-like function double_int::from_buffer.
>>>
>>> The code bootstraps fine on x86-linux-gnu and I have test coverage from
>>> avr-unknown-none.
>>>
>>> Ok to apply?
>>
>> Ok.
>>
>> Thanks,
>> Richard.
>
> Let me drop this, I don't like the name "const_fixed_from_double_int". It's
> bad and I think "fixed_from_double_int" is better. Other constructor-like
> functions for FIXED_VALUE_TYPE use fixed_from_* whereas const_fixed_* returns a
> CONST_FIXED rtx.
>
> This is less confusing and fits better the naming convention.
>
> The new patch also adds const_fixed_from_double_int that actually returns a
> CONST_FIXED rtx. It's unused, but I would use it in the avr back.
>
> Okay with that rename? (Or, at your option, without const_fixed_from_double_int).
Ok.
Thanks,
Richard.
> Johann
>
>
> 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.
>
> testsuite/
> PR tree-optimization/56064
> * gcc.dg/fixed-point/view-convert.c: New test.
>
>
>
>>
>>> There are less intrusive solutions that only handle the int <-> fixed cases,
>>> for example fold-const.c:fold_view_convert_expr() could test for these cases
>>> and use double_int directly without serializing / deserializing through a
>>> memory buffer.
>>>
>>> Johann
>>>
>>>
>>> PR tree-optimization/56064
>>> * fixed-value.c (const_fixed_from_double_int): New function.
>>> * fixed-value.h (const_fixed_from_double_int): New prototype.
>>> * 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.
>>>
>>> testsuite/
>>> PR tree-optimization/56064
>>> * gcc.dg/fixed-point/view-convert.c: New test.
>>
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-01-30 10:36 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-21 13:29 [Patch] PR56064: Fold VIEW_CONVERT_EXPR with FIXED_CST Georg-Johann Lay
2013-01-29 11:27 ` Richard Biener
2013-01-29 20:00 ` [Patch] PR56064: Fold VIEW_CONVERT_EXPR with FIXED_CST, Take #2 Georg-Johann Lay
2013-01-30 10:36 ` Richard Biener
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).