diff options
author | Richard Biener <rguenther@suse.de> | 2016-08-26 12:33:43 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2016-08-26 12:33:43 +0000 |
commit | ebfa15ab654738fcc926a506b3788a303958fa02 (patch) | |
tree | 36a9fb525064b262301c1f5214a7264dd4b939f2 /gcc/tree-ssa.c | |
parent | 52066eae5d3dd6b7c0a1b843469582dbdbb941eb (diff) | |
download | gcc-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.c | 58 |
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; |