On Mon, May 7, 2012 at 2:30 PM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > If returning an addressable result by value, the C++ FE makes > it returned by reference, RESULT_DECL in that case is DECL_BY_REFERENCE > REFERENCE_TYPE. VRP shouldn't in that case assume the <result> is > VR_UNDEFINED, instead it only knows that it is nonnull. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok also for branches (where you think it fits). Thanks, Richard. > 2012-05-07 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/53239 > * tree-vrp.c (get_value_range): Set VR of > SSA_NAME_IS_DEFAULT_DEF of DECL_BY_REFERENCE RESULT_DECL > to nonnull. > > * g++.dg/opt/vrp3.C: New test. > * g++.dg/opt/vrp3-aux.cc: New file. > * g++.dg/opt/vrp3.h: New file. > > --- gcc/tree-vrp.c.jj 2012-03-13 19:59:16.000000000 +0100 > +++ gcc/tree-vrp.c 2012-05-07 08:46:16.008803053 +0200 > @@ -695,17 +695,22 @@ get_value_range (const_tree var) > /* If VAR is a default definition of a parameter, the variable can > take any value in VAR's type. */ > sym = SSA_NAME_VAR (var); > - if (SSA_NAME_IS_DEFAULT_DEF (var) > - && TREE_CODE (sym) == PARM_DECL) > + if (SSA_NAME_IS_DEFAULT_DEF (var)) > { > - /* Try to use the "nonnull" attribute to create ~[0, 0] > - anti-ranges for pointers. Note that this is only valid with > - default definitions of PARM_DECLs. */ > - if (POINTER_TYPE_P (TREE_TYPE (sym)) > - && nonnull_arg_p (sym)) > + if (TREE_CODE (sym) == PARM_DECL) > + { > + /* Try to use the "nonnull" attribute to create ~[0, 0] > + anti-ranges for pointers. Note that this is only valid with > + default definitions of PARM_DECLs. */ > + if (POINTER_TYPE_P (TREE_TYPE (sym)) > + && nonnull_arg_p (sym)) > + set_value_range_to_nonnull (vr, TREE_TYPE (sym)); > + else > + set_value_range_to_varying (vr); > + } > + else if (TREE_CODE (sym) == RESULT_DECL > + && DECL_BY_REFERENCE (sym)) > set_value_range_to_nonnull (vr, TREE_TYPE (sym)); > - else > - set_value_range_to_varying (vr); > } > > return vr; > --- gcc/testsuite/g++.dg/opt/vrp3.C.jj 2012-05-07 09:09:08.574648044 +0200 > +++ gcc/testsuite/g++.dg/opt/vrp3.C 2012-05-07 09:09:03.138678376 +0200 > @@ -0,0 +1,47 @@ > +// PR tree-optimization/53239 > +// { dg-do run } > +// { dg-options "-O2" } > +// { dg-additional-sources "vrp3-aux.cc" } > + > +#include "vrp3.h" > + > +struct M > +{ > + M (R m); > + R val; > + static int compare (M const &, M const &); > +}; > + > +inline M const & > +min (M const & t1, M const & t2) > +{ > + return R::compare (t1.val, t2.val) < 0 ? t1 : t2; > +} > + > +M::M (R m) > +{ > + val = m; > +} > + > +M > +test (M *x) > +{ > + M n (R (0, 0)); > + > + for (int i = 0; i < 2; i++) > + { > + M p = x[i]; > + n = min (n, p); > + } > + > + if (n.val.r2 != 2 || n.val.r1 != 1) > + __builtin_abort (); > + return n; > +} > + > +int > +main () > +{ > + M x[2] = { M (R (1, 2)), M (R (1, 1)) }; > + test (x); > +} > --- gcc/testsuite/g++.dg/opt/vrp3-aux.cc.jj 2012-05-07 09:09:22.060567366 > +0200 > +++ gcc/testsuite/g++.dg/opt/vrp3-aux.cc 2012-05-07 09:09:28.538528045 > +0200 > @@ -0,0 +1,21 @@ > +// { dg-do compile } > +// { dg-options "" } > + > +#include "vrp3.h" > + > +R::R () > +{ > + r1 = r2 = 1; > +} > + > +R::R (int n, int d) > +{ > + r1 = n; > + r2 = d; > +} > + > +int > +R::compare (R const &r, R const &s) > +{ > + return (int) (r.r1 * s.r2 - s.r1 * r.r2); > +} > --- gcc/testsuite/g++.dg/opt/vrp3.h.jj 2012-05-07 09:09:41.402448593 +0200 > +++ gcc/testsuite/g++.dg/opt/vrp3.h 2012-05-07 09:09:46.509420562 +0200 > @@ -0,0 +1,9 @@ > +struct R > +{ > + long long r1, r2; > + void copy (R const &r) { r1 = r.r1; r2 = r.r2; } > + R (); > + explicit R (int, int); > + R (R const &r) { copy (r); } > + static int compare (R const &, R const &); > +}; > > Jakub