diff mbox

Fix VRP with DECL_BY_REFERENCE RESULT_DECLs (PR tree-optimization/53239)

Message ID 20120507123024.GG16117@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek May 7, 2012, 12:30 p.m. UTC
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?

2012-05-07  Jakub Jelinek  <jakub@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.


	Jakub

Comments

Richard Biener May 7, 2012, 12:46 p.m. UTC | #1
On Mon, May 7, 2012 at 2:30 PM, Jakub Jelinek <jakub@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  <jakub@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
diff mbox

Patch

--- 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 &);
+};