re PR tree-optimization/69047 (memcpy is not as optimized as union is)

2016-08-26  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/69047
	* tree-ssa.c (maybe_rewrite_mem_ref_base): Handle general bitfield
	extracts similar to what FRE does.
	(non_rewritable_mem_ref_base): Likewise.

	* gcc.dg/pr69047.c: New testcase.

From-SVN: r239778
This commit is contained in:
Richard Biener 2016-08-26 12:33:43 +00:00 committed by Richard Biener
parent 52066eae5d
commit ebfa15ab65
4 changed files with 80 additions and 8 deletions

View File

@ -1,3 +1,10 @@
2016-08-26 Richard Biener <rguenther@suse.de>
PR tree-optimization/69047
* tree-ssa.c (maybe_rewrite_mem_ref_base): Handle general bitfield
extracts similar to what FRE does.
(non_rewritable_mem_ref_base): Likewise.
2016-08-26 Joseph Myers <joseph@codesourcery.com>
* config/i386/i386.c (ix86_libgcc_floating_mode_supported_p)

View File

@ -1,3 +1,8 @@
2016-08-26 Richard Biener <rguenther@suse.de>
PR tree-optimization/69047
* gcc.dg/pr69047.c: New testcase.
2016-08-26 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
Martin Jambhor <mjambor@suse.cz>

View File

@ -0,0 +1,18 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-cddce1" } */
__UINT8_TYPE__
f(__UINT16_TYPE__ b)
{
__UINT8_TYPE__ a;
#if __BYTE_ORDER == __LITTLE_ENDIAN
__builtin_memcpy(&a, &b, sizeof a);
#elif __BYTE_ORDER == __BIG_ENDIAN
__builtin_memcpy(&a, (char *)&b + sizeof a, sizeof a);
#else
a = b;
#endif
return a;
}
/* { dg-final { scan-tree-dump "_\[0-9\]+ = \\(\[^)\]+\\) b" "cddce1" } } */

View File

@ -1292,7 +1292,9 @@ maybe_rewrite_mem_ref_base (tree *tp, bitmap suitable_for_renaming)
&& (sym = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0))
&& DECL_P (sym)
&& !TREE_ADDRESSABLE (sym)
&& bitmap_bit_p (suitable_for_renaming, DECL_UID (sym)))
&& bitmap_bit_p (suitable_for_renaming, DECL_UID (sym))
&& is_gimple_reg_type (TREE_TYPE (*tp))
&& ! VOID_TYPE_P (TREE_TYPE (*tp)))
{
if (TREE_CODE (TREE_TYPE (sym)) == VECTOR_TYPE
&& useless_type_conversion_p (TREE_TYPE (*tp),
@ -1314,7 +1316,8 @@ maybe_rewrite_mem_ref_base (tree *tp, bitmap suitable_for_renaming)
? REALPART_EXPR : IMAGPART_EXPR,
TREE_TYPE (*tp), sym);
}
else if (integer_zerop (TREE_OPERAND (*tp, 1)))
else if (integer_zerop (TREE_OPERAND (*tp, 1))
&& DECL_SIZE (sym) == TYPE_SIZE (TREE_TYPE (*tp)))
{
if (!useless_type_conversion_p (TREE_TYPE (*tp),
TREE_TYPE (sym)))
@ -1323,6 +1326,24 @@ maybe_rewrite_mem_ref_base (tree *tp, bitmap suitable_for_renaming)
else
*tp = sym;
}
else if (DECL_SIZE (sym)
&& TREE_CODE (DECL_SIZE (sym)) == INTEGER_CST
&& mem_ref_offset (*tp) >= 0
&& wi::leu_p (mem_ref_offset (*tp)
+ wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (*tp))),
wi::to_offset (DECL_SIZE_UNIT (sym)))
&& (! INTEGRAL_TYPE_P (TREE_TYPE (*tp))
|| (wi::to_offset (TYPE_SIZE (TREE_TYPE (*tp)))
== TYPE_PRECISION (TREE_TYPE (*tp))))
&& wi::umod_trunc (wi::to_offset (TYPE_SIZE (TREE_TYPE (*tp))),
BITS_PER_UNIT) == 0)
{
*tp = build3 (BIT_FIELD_REF, TREE_TYPE (*tp), sym,
TYPE_SIZE (TREE_TYPE (*tp)),
wide_int_to_tree (bitsizetype,
mem_ref_offset (*tp)
<< LOG2_BITS_PER_UNIT));
}
}
}
@ -1352,6 +1373,11 @@ non_rewritable_mem_ref_base (tree ref)
&& TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR)
{
tree decl = TREE_OPERAND (TREE_OPERAND (base, 0), 0);
if (! DECL_P (decl))
return NULL_TREE;
if (! is_gimple_reg_type (TREE_TYPE (base))
|| VOID_TYPE_P (TREE_TYPE (base)))
return decl;
if ((TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE)
&& useless_type_conversion_p (TREE_TYPE (base),
@ -1362,12 +1388,28 @@ non_rewritable_mem_ref_base (tree ref)
&& multiple_of_p (sizetype, TREE_OPERAND (base, 1),
TYPE_SIZE_UNIT (TREE_TYPE (base))))
return NULL_TREE;
if (DECL_P (decl)
&& (!integer_zerop (TREE_OPERAND (base, 1))
|| (DECL_SIZE (decl)
!= TYPE_SIZE (TREE_TYPE (base)))
|| TREE_THIS_VOLATILE (decl) != TREE_THIS_VOLATILE (base)))
return decl;
/* For same sizes and zero offset we can use a VIEW_CONVERT_EXPR. */
if (integer_zerop (TREE_OPERAND (base, 1))
&& DECL_SIZE (decl) == TYPE_SIZE (TREE_TYPE (base)))
return NULL_TREE;
/* For integral typed extracts we can use a BIT_FIELD_REF. */
if (DECL_SIZE (decl)
&& TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST
&& mem_ref_offset (base) >= 0
&& wi::leu_p (mem_ref_offset (base)
+ wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (base))),
wi::to_offset (DECL_SIZE_UNIT (decl)))
/* ??? We can't handle bitfield precision extracts without
either using an alternate type for the BIT_FIELD_REF and
then doing a conversion or possibly adjusting the offset
according to endianess. */
&& (! INTEGRAL_TYPE_P (TREE_TYPE (base))
|| (wi::to_offset (TYPE_SIZE (TREE_TYPE (base)))
== TYPE_PRECISION (TREE_TYPE (base))))
&& wi::umod_trunc (wi::to_offset (TYPE_SIZE (TREE_TYPE (base))),
BITS_PER_UNIT) == 0)
return NULL_TREE;
return decl;
}
return NULL_TREE;