This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR47621
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 7 Feb 2011 12:59:18 +0100 (CET)
- Subject: [PATCH] Fix PR47621
This fixes PR47621, while we can in theory handle some
component-references when writing vars into SSA form (in particular
indirects through union types) an earlier patch enabled pre-existing
code by chance and that code was broken with regarding to
component-ref handing. The following patch makes us conservative again,
not handling component-refs for now, but keeping the original intent
of the code.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard.
2011-02-07 Richard Guenther <rguenther@suse.de>
PR tree-optimization/47621
* tree-ssa.c (non_rewritable_lvalue_p): New function, split out from
two duplicates ...
(execute_update_addresses_taken): ... here. Make it more
conservative in what we accept.
* gcc.dg/torture/pr47621.c: New testcase.
Index: gcc/tree-ssa.c
===================================================================
*** gcc/tree-ssa.c.orig 2011-01-14 13:27:05.000000000 +0100
--- gcc/tree-ssa.c 2011-02-07 11:30:43.000000000 +0100
*************** non_rewritable_mem_ref_base (tree ref)
*** 1885,1890 ****
--- 1885,1918 ----
return NULL_TREE;
}
+ /* For an lvalue tree LHS return true if it cannot be rewritten into SSA form.
+ Otherwise return true. */
+
+ static bool
+ non_rewritable_lvalue_p (tree lhs)
+ {
+ /* A plain decl is always rewritable. */
+ if (DECL_P (lhs))
+ return false;
+
+ /* A decl that is wrapped inside a MEM-REF that covers
+ it full is also rewritable.
+ ??? The following could be relaxed allowing component
+ references that do not change the access size. */ ;
+ if (TREE_CODE (lhs) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR
+ && integer_zerop (TREE_OPERAND (lhs, 1)))
+ {
+ tree decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0);
+ if (DECL_P (decl)
+ && DECL_SIZE (decl) == TYPE_SIZE (TREE_TYPE (lhs))
+ && (TREE_THIS_VOLATILE (decl) == TREE_THIS_VOLATILE (lhs)))
+ return false;
+ }
+
+ return true;
+ }
+
/* When possible, clear TREE_ADDRESSABLE bit or set DECL_GIMPLE_REG_P bit and
mark the variable VAR for conversion into SSA. Return true when updating
stmts is required. */
*************** execute_update_addresses_taken (void)
*** 1978,2006 ****
if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
{
tree lhs = gimple_get_lhs (stmt);
!
! /* A plain decl does not need it set. */
! if (lhs && !DECL_P (lhs))
{
! tree orig_lhs = lhs;
!
! while (handled_component_p (lhs))
! lhs = TREE_OPERAND (lhs, 0);
!
! if (DECL_P (lhs))
! bitmap_set_bit (not_reg_needs, DECL_UID (lhs));
! else if (TREE_CODE (lhs) == MEM_REF
! && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR)
! {
! decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0);
! if (DECL_P (decl)
! && (!integer_zerop (TREE_OPERAND (lhs, 1))
! || (DECL_SIZE (decl)
! != TYPE_SIZE (TREE_TYPE (orig_lhs)))
! || (TREE_THIS_VOLATILE (lhs)
! != TREE_THIS_VOLATILE (decl))))
! bitmap_set_bit (not_reg_needs, DECL_UID (decl));
! }
}
}
--- 2006,2018 ----
if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
{
tree lhs = gimple_get_lhs (stmt);
! if (lhs
! && TREE_CODE (lhs) != SSA_NAME
! && non_rewritable_lvalue_p (lhs))
{
! decl = get_base_address (lhs);
! if (DECL_P (decl))
! bitmap_set_bit (not_reg_needs, DECL_UID (decl));
}
}
*************** execute_update_addresses_taken (void)
*** 2027,2055 ****
{
tree link = gimple_asm_output_op (stmt, i);
tree lhs = TREE_VALUE (link);
!
! /* A plain decl does not need it set. */
! if (!DECL_P (lhs))
{
! tree orig_lhs = lhs;
!
! while (handled_component_p (lhs))
! lhs = TREE_OPERAND (lhs, 0);
!
! if (DECL_P (lhs))
! bitmap_set_bit (not_reg_needs, DECL_UID (lhs));
! else if (TREE_CODE (lhs) == MEM_REF
! && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR)
! {
! decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0);
! if (DECL_P (decl)
! && (!integer_zerop (TREE_OPERAND (lhs, 1))
! || (TYPE_MAIN_VARIANT (TREE_TYPE (decl))
! != TYPE_MAIN_VARIANT (TREE_TYPE (orig_lhs)))
! || (TREE_THIS_VOLATILE (lhs)
! != TREE_THIS_VOLATILE (decl))))
! bitmap_set_bit (not_reg_needs, DECL_UID (decl));
! }
}
}
for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
--- 2039,2050 ----
{
tree link = gimple_asm_output_op (stmt, i);
tree lhs = TREE_VALUE (link);
! if (TREE_CODE (lhs) != SSA_NAME
! && non_rewritable_lvalue_p (lhs))
{
! decl = get_base_address (lhs);
! if (DECL_P (decl))
! bitmap_set_bit (not_reg_needs, DECL_UID (decl));
}
}
for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
Index: gcc/testsuite/gcc.dg/torture/pr47621.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/torture/pr47621.c 2011-02-07 11:29:43.000000000 +0100
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do run } */
+
+ extern void abort (void);
+
+ int
+ main (void)
+ {
+ int data = 1;
+ struct ptr { int val; } *ptr = (struct ptr *) &data;
+ ptr->val = 0;
+ if (data != 0)
+ abort ();
+ return 0;
+ }