aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2016-08-26 12:33:43 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2016-08-26 12:33:43 +0000
commitebfa15ab654738fcc926a506b3788a303958fa02 (patch)
tree36a9fb525064b262301c1f5214a7264dd4b939f2 /gcc/tree-ssa.c
parent52066eae5d3dd6b7c0a1b843469582dbdbb941eb (diff)
downloadgcc-ebfa15ab654738fcc926a506b3788a303958fa02.zip
gcc-ebfa15ab654738fcc926a506b3788a303958fa02.tar.gz
gcc-ebfa15ab654738fcc926a506b3788a303958fa02.tar.bz2
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
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r--gcc/tree-ssa.c58
1 files changed, 50 insertions, 8 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 66b50b9..aae383d 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -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;