diff mbox

Further VRP improvements

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

Commit Message

Jakub Jelinek March 8, 2012, 3:54 p.m. UTC
Hi!

This patch adds ASSERT_EXPRs for
if ((int) var cmp CST)
(for cmp >, >=, <, <=).  As the testcase shows, various different tests
are folded into that form.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2012-03-08  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/51721
	* tree-vrp.c (register_edge_assert_for_2): Add asserts for unsvar
	if (int) unsvar cmp CST.

	* gcc.dg/tree-ssa/vrp64.c: New test.


	Jakub

Comments

Richard Biener March 12, 2012, 11:08 a.m. UTC | #1
On Thu, 8 Mar 2012, Jakub Jelinek wrote:

> Hi!
> 
> This patch adds ASSERT_EXPRs for
> if ((int) var cmp CST)
> (for cmp >, >=, <, <=).  As the testcase shows, various different tests
> are folded into that form.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.

Thanks,
Richard.

> 2012-03-08  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/51721
> 	* tree-vrp.c (register_edge_assert_for_2): Add asserts for unsvar
> 	if (int) unsvar cmp CST.
> 
> 	* gcc.dg/tree-ssa/vrp64.c: New test.
> 
> --- gcc/tree-vrp.c.jj	2012-03-06 17:02:12.000000000 +0100
> +++ gcc/tree-vrp.c	2012-03-08 11:41:17.749509390 +0100
> @@ -4462,8 +4462,6 @@ register_edge_assert_for_2 (tree name, e
>  	}
>      }
>  
> -  /* Similarly add asserts for NAME == CST and NAME being defined as
> -     NAME = NAME2 >> CST2.  */
>    if (TREE_CODE_CLASS (comp_code) == tcc_comparison
>        && TREE_CODE (val) == INTEGER_CST)
>      {
> @@ -4472,7 +4470,61 @@ register_edge_assert_for_2 (tree name, e
>        tree val2 = NULL_TREE;
>        unsigned HOST_WIDE_INT mask[2] = { 0, 0 };
>  
> -      /* Extract CST2 from the right shift.  */
> +      /* Add asserts for NAME cmp CST and NAME being defined
> +	 as NAME = (int) NAME2.  */
> +      if (!TYPE_UNSIGNED (TREE_TYPE (val))
> +	  && (comp_code == LE_EXPR || comp_code == LT_EXPR
> +	      || comp_code == GT_EXPR || comp_code == GE_EXPR)
> +	  && gimple_assign_cast_p (def_stmt))
> +	{
> +	  name2 = gimple_assign_rhs1 (def_stmt);
> +	  if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
> +	      && INTEGRAL_TYPE_P (TREE_TYPE (name2))
> +	      && TYPE_UNSIGNED (TREE_TYPE (name2))
> +	      && (TYPE_PRECISION (TREE_TYPE (val))
> +		  == TYPE_PRECISION (TREE_TYPE (name2)))
> +	      && (comp_code == LE_EXPR || comp_code == GT_EXPR
> +		  || !tree_int_cst_equal (val,
> +					  TYPE_MIN_VALUE (TREE_TYPE (val))))
> +	      && live_on_edge (e, name2)
> +	      && !has_single_use (name2))
> +	    {
> +	      tree tmp, cst;
> +	      enum tree_code new_comp_code = comp_code;
> +
> +	      cst = fold_convert (TREE_TYPE (name2),
> +				  TYPE_MIN_VALUE (TREE_TYPE (val)));
> +	      /* Build an expression for the range test.  */
> +	      tmp = build2 (PLUS_EXPR, TREE_TYPE (name2), name2, cst);
> +	      cst = fold_build2 (PLUS_EXPR, TREE_TYPE (name2), cst,
> +				 fold_convert (TREE_TYPE (name2), val));
> +	      if (comp_code == LT_EXPR || comp_code == GE_EXPR)
> +		{
> +		  new_comp_code = comp_code == LT_EXPR ? LE_EXPR : GT_EXPR;
> +		  cst = fold_build2 (MINUS_EXPR, TREE_TYPE (name2), cst,
> +				     build_int_cst (TREE_TYPE (name2), 1));
> +		}
> +
> +	      if (dump_file)
> +		{
> +		  fprintf (dump_file, "Adding assert for ");
> +		  print_generic_expr (dump_file, name2, 0);
> +		  fprintf (dump_file, " from ");
> +		  print_generic_expr (dump_file, tmp, 0);
> +		  fprintf (dump_file, "\n");
> +		}
> +
> +	      register_new_assert_for (name2, tmp, new_comp_code, cst, NULL,
> +				       e, bsi);
> +
> +	      retval = true;
> +	    }
> +	}
> +
> +      /* Add asserts for NAME cmp CST and NAME being defined as
> +	 NAME = NAME2 >> CST2.
> +
> +	 Extract CST2 from the right shift.  */
>        if (is_gimple_assign (def_stmt)
>  	  && gimple_assign_rhs_code (def_stmt) == RSHIFT_EXPR)
>  	{
> @@ -4500,7 +4552,6 @@ register_edge_assert_for_2 (tree name, e
>  	      val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2);
>  	    }
>  	}
> -
>        if (val2 != NULL_TREE
>  	  && TREE_CODE (val2) == INTEGER_CST
>  	  && simple_cst_equal (fold_build2 (RSHIFT_EXPR,
> --- gcc/testsuite/gcc.dg/tree-ssa/vrp64.c.jj	2012-03-08 12:58:05.773797384 +0100
> +++ gcc/testsuite/gcc.dg/tree-ssa/vrp64.c	2012-03-08 12:57:26.000000000 +0100
> @@ -0,0 +1,152 @@
> +/* PR tree-optimization/51721 */
> +/* { dg-do link } */
> +/* { dg-options "-O2" } */
> +
> +extern void link_error (void);
> +
> +#define BITSM1 (sizeof (int) * __CHAR_BIT__ - 1)
> +
> +void
> +f1 (unsigned int s)
> +{
> +  if (s >> BITSM1 != 0)
> +    {
> +      if (s == 0 || s == 5 || s == __INT_MAX__)
> +	link_error ();
> +    }
> +  else
> +    {
> +      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U)
> +	link_error ();
> +    }
> +}
> +
> +void
> +f2 (int s)
> +{
> +  if (s >> BITSM1 == 0)
> +    {
> +      if (s == -1 || s == -5 || s == -__INT_MAX__ - 1)
> +	link_error ();
> +    }
> +  else
> +    {
> +      if (s == 0 || s == 5 || s == __INT_MAX__)
> +	link_error ();
> +    }
> +}
> +
> +void
> +f3 (unsigned int s)
> +{
> +  if ((s & (1U << BITSM1)) != 0)
> +    {
> +      if (s == 0 || s == 5 || s == __INT_MAX__)
> +	link_error ();
> +    }
> +  else
> +    {
> +      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U)
> +	link_error ();
> +    }
> +}
> +
> +void
> +f4 (int s)
> +{
> +  if ((s & (1U << BITSM1)) == 0)
> +    {
> +      if (s == -1 || s == -5 || s == -__INT_MAX__ - 1)
> +	link_error ();
> +    }
> +  else
> +    {
> +      if (s == 0 || s == 5 || s == __INT_MAX__)
> +	link_error ();
> +    }
> +}
> +
> +void
> +f5 (unsigned int s)
> +{
> +  if ((int) s < 0)
> +    {
> +      if (s == 0 || s == 5 || s == __INT_MAX__)
> +	link_error ();
> +    }
> +  else
> +    {
> +      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U)
> +	link_error ();
> +    }
> +}
> +
> +void
> +f6 (unsigned int s)
> +{
> +  if ((int) s < 4)
> +    {
> +      if (s == 4 || s == 6 || s == __INT_MAX__)
> +	link_error ();
> +    }
> +  else
> +    {
> +      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U
> +	  || s == 3 || s == 0)
> +	link_error ();
> +    }
> +}
> +
> +void
> +f7 (unsigned int s)
> +{
> +  if ((int) s <= -7)
> +    {
> +      if (s == -6U || s == -1U || s == 0 || s == 4 || s == 6 || s == __INT_MAX__)
> +	link_error ();
> +    }
> +  else
> +    {
> +      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -9U
> +	  || s == -7U)
> +	link_error ();
> +    }
> +}
> +
> +void
> +f8 (unsigned int s)
> +{
> +  if ((int) s >= 4)
> +    {
> +      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U
> +	  || s == 3 || s == 0)
> +	link_error ();
> +    }
> +  else
> +    {
> +      if (s == 4 || s == 6 || s == __INT_MAX__)
> +	link_error ();
> +    }
> +}
> +
> +void
> +f9 (unsigned int s)
> +{
> +  if ((int) s > -7)
> +    {
> +      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -9U
> +	  || s == -7U)
> +	link_error ();
> +    }
> +  else
> +    {
> +      if (s == -6U || s == -1U || s == 0 || s == 4 || s == 6 || s == __INT_MAX__)
> +	link_error ();
> +    }
> +}
> +
> +int
> +main ()
> +{
> +  return 0;
> +}
> 
> 	Jakub
> 
>
diff mbox

Patch

--- gcc/tree-vrp.c.jj	2012-03-06 17:02:12.000000000 +0100
+++ gcc/tree-vrp.c	2012-03-08 11:41:17.749509390 +0100
@@ -4462,8 +4462,6 @@  register_edge_assert_for_2 (tree name, e
 	}
     }
 
-  /* Similarly add asserts for NAME == CST and NAME being defined as
-     NAME = NAME2 >> CST2.  */
   if (TREE_CODE_CLASS (comp_code) == tcc_comparison
       && TREE_CODE (val) == INTEGER_CST)
     {
@@ -4472,7 +4470,61 @@  register_edge_assert_for_2 (tree name, e
       tree val2 = NULL_TREE;
       unsigned HOST_WIDE_INT mask[2] = { 0, 0 };
 
-      /* Extract CST2 from the right shift.  */
+      /* Add asserts for NAME cmp CST and NAME being defined
+	 as NAME = (int) NAME2.  */
+      if (!TYPE_UNSIGNED (TREE_TYPE (val))
+	  && (comp_code == LE_EXPR || comp_code == LT_EXPR
+	      || comp_code == GT_EXPR || comp_code == GE_EXPR)
+	  && gimple_assign_cast_p (def_stmt))
+	{
+	  name2 = gimple_assign_rhs1 (def_stmt);
+	  if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))
+	      && INTEGRAL_TYPE_P (TREE_TYPE (name2))
+	      && TYPE_UNSIGNED (TREE_TYPE (name2))
+	      && (TYPE_PRECISION (TREE_TYPE (val))
+		  == TYPE_PRECISION (TREE_TYPE (name2)))
+	      && (comp_code == LE_EXPR || comp_code == GT_EXPR
+		  || !tree_int_cst_equal (val,
+					  TYPE_MIN_VALUE (TREE_TYPE (val))))
+	      && live_on_edge (e, name2)
+	      && !has_single_use (name2))
+	    {
+	      tree tmp, cst;
+	      enum tree_code new_comp_code = comp_code;
+
+	      cst = fold_convert (TREE_TYPE (name2),
+				  TYPE_MIN_VALUE (TREE_TYPE (val)));
+	      /* Build an expression for the range test.  */
+	      tmp = build2 (PLUS_EXPR, TREE_TYPE (name2), name2, cst);
+	      cst = fold_build2 (PLUS_EXPR, TREE_TYPE (name2), cst,
+				 fold_convert (TREE_TYPE (name2), val));
+	      if (comp_code == LT_EXPR || comp_code == GE_EXPR)
+		{
+		  new_comp_code = comp_code == LT_EXPR ? LE_EXPR : GT_EXPR;
+		  cst = fold_build2 (MINUS_EXPR, TREE_TYPE (name2), cst,
+				     build_int_cst (TREE_TYPE (name2), 1));
+		}
+
+	      if (dump_file)
+		{
+		  fprintf (dump_file, "Adding assert for ");
+		  print_generic_expr (dump_file, name2, 0);
+		  fprintf (dump_file, " from ");
+		  print_generic_expr (dump_file, tmp, 0);
+		  fprintf (dump_file, "\n");
+		}
+
+	      register_new_assert_for (name2, tmp, new_comp_code, cst, NULL,
+				       e, bsi);
+
+	      retval = true;
+	    }
+	}
+
+      /* Add asserts for NAME cmp CST and NAME being defined as
+	 NAME = NAME2 >> CST2.
+
+	 Extract CST2 from the right shift.  */
       if (is_gimple_assign (def_stmt)
 	  && gimple_assign_rhs_code (def_stmt) == RSHIFT_EXPR)
 	{
@@ -4500,7 +4552,6 @@  register_edge_assert_for_2 (tree name, e
 	      val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2);
 	    }
 	}
-
       if (val2 != NULL_TREE
 	  && TREE_CODE (val2) == INTEGER_CST
 	  && simple_cst_equal (fold_build2 (RSHIFT_EXPR,
--- gcc/testsuite/gcc.dg/tree-ssa/vrp64.c.jj	2012-03-08 12:58:05.773797384 +0100
+++ gcc/testsuite/gcc.dg/tree-ssa/vrp64.c	2012-03-08 12:57:26.000000000 +0100
@@ -0,0 +1,152 @@ 
+/* PR tree-optimization/51721 */
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+extern void link_error (void);
+
+#define BITSM1 (sizeof (int) * __CHAR_BIT__ - 1)
+
+void
+f1 (unsigned int s)
+{
+  if (s >> BITSM1 != 0)
+    {
+      if (s == 0 || s == 5 || s == __INT_MAX__)
+	link_error ();
+    }
+  else
+    {
+      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U)
+	link_error ();
+    }
+}
+
+void
+f2 (int s)
+{
+  if (s >> BITSM1 == 0)
+    {
+      if (s == -1 || s == -5 || s == -__INT_MAX__ - 1)
+	link_error ();
+    }
+  else
+    {
+      if (s == 0 || s == 5 || s == __INT_MAX__)
+	link_error ();
+    }
+}
+
+void
+f3 (unsigned int s)
+{
+  if ((s & (1U << BITSM1)) != 0)
+    {
+      if (s == 0 || s == 5 || s == __INT_MAX__)
+	link_error ();
+    }
+  else
+    {
+      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U)
+	link_error ();
+    }
+}
+
+void
+f4 (int s)
+{
+  if ((s & (1U << BITSM1)) == 0)
+    {
+      if (s == -1 || s == -5 || s == -__INT_MAX__ - 1)
+	link_error ();
+    }
+  else
+    {
+      if (s == 0 || s == 5 || s == __INT_MAX__)
+	link_error ();
+    }
+}
+
+void
+f5 (unsigned int s)
+{
+  if ((int) s < 0)
+    {
+      if (s == 0 || s == 5 || s == __INT_MAX__)
+	link_error ();
+    }
+  else
+    {
+      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U)
+	link_error ();
+    }
+}
+
+void
+f6 (unsigned int s)
+{
+  if ((int) s < 4)
+    {
+      if (s == 4 || s == 6 || s == __INT_MAX__)
+	link_error ();
+    }
+  else
+    {
+      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U
+	  || s == 3 || s == 0)
+	link_error ();
+    }
+}
+
+void
+f7 (unsigned int s)
+{
+  if ((int) s <= -7)
+    {
+      if (s == -6U || s == -1U || s == 0 || s == 4 || s == 6 || s == __INT_MAX__)
+	link_error ();
+    }
+  else
+    {
+      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -9U
+	  || s == -7U)
+	link_error ();
+    }
+}
+
+void
+f8 (unsigned int s)
+{
+  if ((int) s >= 4)
+    {
+      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U
+	  || s == 3 || s == 0)
+	link_error ();
+    }
+  else
+    {
+      if (s == 4 || s == 6 || s == __INT_MAX__)
+	link_error ();
+    }
+}
+
+void
+f9 (unsigned int s)
+{
+  if ((int) s > -7)
+    {
+      if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -9U
+	  || s == -7U)
+	link_error ();
+    }
+  else
+    {
+      if (s == -6U || s == -1U || s == 0 || s == 4 || s == 6 || s == __INT_MAX__)
+	link_error ();
+    }
+}
+
+int
+main ()
+{
+  return 0;
+}