diff options
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr69047.c | 18 | ||||
-rw-r--r-- | gcc/tree-ssa.c | 58 |
4 files changed, 80 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e8917e3..408b715 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e51756d..86ef6a0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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> diff --git a/gcc/testsuite/gcc.dg/pr69047.c b/gcc/testsuite/gcc.dg/pr69047.c new file mode 100644 index 0000000..0227df2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr69047.c @@ -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" } } */ 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; |