diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 01412bd0961..d25e30c1bd1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2011-01-05 Eric Botcazou + + PR tree-optimization/47005 + * tree-sra.c (struct access): Add 'non_addressable' bit. + (create_access): Set it for a DECL_NONADDRESSABLE_P field. + (decide_one_param_reduction): Return 0 if the parameter is passed by + reference and one of the accesses in the group is non_addressable. + 2011-01-04 Eric Botcazou PR tree-optimization/47056 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 208304ce79a..867e6a09550 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-01-05 Eric Botcazou + + * gnat.dg/opt14.adb: New test. + 2011-01-05 Thomas Koenig PR fortran/46017 diff --git a/gcc/testsuite/gnat.dg/opt14.adb b/gcc/testsuite/gnat.dg/opt14.adb new file mode 100644 index 00000000000..61bc7313bb5 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt14.adb @@ -0,0 +1,25 @@ +-- { dg-do run } +-- { dg-options "-O2" } + +procedure Opt14 is + + type Rec is record + I1, I2, I3 : Integer; + end record; + + type Ptr is access Rec; + + P : Ptr := new Rec'(0,0,0); + + procedure Sub (R : In Out Rec) is + begin + R.I3 := R.I3 - 1; + end; + +begin + P.all := (1,2,3); + Sub (P.all); + if P.all /= (1,2,2) then + raise Program_Error; + end if; +end; diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 14fef477485..c2ec2042932 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -173,6 +173,9 @@ struct access entirely? */ unsigned total_scalarization : 1; + /* Is this access an access to a non-addressable field? */ + unsigned non_addressable : 1; + /* Is this access currently in the work queue? */ unsigned grp_queued : 1; @@ -816,6 +819,10 @@ create_access (tree expr, gimple stmt, bool write) access->grp_unscalarizable_region = unscalarizable_region; access->stmt = stmt; + if (TREE_CODE (expr) == COMPONENT_REF + && DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1))) + access->non_addressable = 1; + return access; } @@ -3666,13 +3673,18 @@ decide_one_param_reduction (struct access *repr) for (; repr; repr = repr->next_grp) { gcc_assert (parm == repr->base); - new_param_count++; + + /* Taking the address of a non-addressable field is verboten. */ + if (by_ref && repr->non_addressable) + return 0; if (!by_ref || (!repr->grp_maybe_modified && !repr->grp_not_necessarilly_dereferenced)) total_size += repr->size; else total_size += cur_parm_size; + + new_param_count++; } gcc_assert (new_param_count > 0);