[PATCH] Refactor assert expr finding in VRP to re-use it from EVRP

Richard Biener rguenther@suse.de
Thu Apr 27 14:04:00 GMT 2017


This refactors register_edge_assert_for_* so that EVRP can use the
"advanced" extraction of ranges from conditions.  It is a re-send
of one part of a series from last December, third part first (and
thus slightly different).

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2016-12-02  Richard Biener  <rguenther@suse.de>

	* tree-vrp.c (assert_info): New struct.
	(add_assert_info): New helper.
	(register_edge_assert_for_2): Refactor to add asserts to a vector
	of assert_info.
	(register_edge_assert_for_1): Likewise.
	(register_edge_assert_for): Likewise.
	(finish_register_edge_assert_for): New helper actually registering
	asserts where live on edge.
	(find_conditional_asserts): Adjust.
	(find_switch_asserts): Likewise.
	(evrp_dom_walker::try_find_new_range): Generalize.
	(evrp_dom_walker::before_dom_children): Use register_edge_assert_for.

	* gcc.dg/tree-ssa/evrp7.c: New testcase.
	* gcc.dg/tree-ssa/evrp8.c: Likewise.
	* gcc.dg/tree-ssa/evrp9.c: Likewise.
	* gcc.dg/tree-ssa/vrp35.c: Disable EVRP.
	* gcc.dg/tree-ssa/vrp36.c: Likewise.
	* gcc.dg/tree-ssa/pr49039.c: Likewise.

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c	(revision 247293)
--- gcc/tree-vrp.c	(working copy)
*************** static tree vrp_evaluate_conditional_war
*** 89,94 ****
--- 89,109 ----
  						     tree, tree, bool, bool *,
  						     bool *);
  
+ struct assert_info
+ {
+   /* Predicate code for the ASSERT_EXPR.  Must be COMPARISON_CLASS_P.  */
+   enum tree_code comp_code;
+ 
+   /* Name to register the assert for.  */
+   tree name;
+ 
+   /* Value being compared against.  */
+   tree val;
+ 
+   /* Expression to compare.  */
+   tree expr;
+ };
+ 
  /* Location information for ASSERT_EXPRs.  Each instance of this
     structure describes an ASSERT_EXPR for an SSA name.  Since a single
     SSA name may have more than one assertion associated with it, these
*************** debug_all_asserts (void)
*** 5029,5034 ****
--- 5044,5062 ----
    dump_all_asserts (stderr);
  }
  
+ /* Push the assert info for NAME, EXPR, COMP_CODE and VAL to ASSERTS.  */
+ 
+ static void
+ add_assert_info (vec<assert_info> &asserts,
+ 		 tree name, tree expr, enum tree_code comp_code, tree val)
+ {
+   assert_info info;
+   info.comp_code = comp_code;
+   info.name = name;
+   info.val = val;
+   info.expr = expr;
+   asserts.safe_push (info);
+ }
  
  /* If NAME doesn't have an ASSERT_EXPR registered for asserting
     'EXPR COMP_CODE VAL' at a location that dominates block BB or
*************** overflow_comparison_p (tree_code code, t
*** 5357,5365 ****
     Invert the condition COND if INVERT is true.  */
  
  static void
! register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
  			    enum tree_code cond_code,
! 			    tree cond_op0, tree cond_op1, bool invert)
  {
    tree val;
    enum tree_code comp_code;
--- 5385,5394 ----
     Invert the condition COND if INVERT is true.  */
  
  static void
! register_edge_assert_for_2 (tree name, edge e,
  			    enum tree_code cond_code,
! 			    tree cond_op0, tree cond_op1, bool invert,
! 			    vec<assert_info> &asserts)
  {
    tree val;
    enum tree_code comp_code;
*************** register_edge_assert_for_2 (tree name, e
*** 5370,5389 ****
  						invert, &comp_code, &val))
      return;
  
!   /* Only register an ASSERT_EXPR if NAME was found in the sub-graph
!      reachable from E.  */
!   if (live_on_edge (e, name))
!     {
!       tree x;
!       if (overflow_comparison_p (comp_code, name, val, false, &x))
! 	{
! 	  enum tree_code new_code
! 	    = ((comp_code == GT_EXPR || comp_code == GE_EXPR)
! 	       ? GT_EXPR : LE_EXPR);
! 	  register_new_assert_for (name, name, new_code, x, NULL, e, bsi);
! 	}
!       register_new_assert_for (name, name, comp_code, val, NULL, e, bsi);
      }
  
    /* In the case of NAME <= CST and NAME being defined as
       NAME = (unsigned) NAME2 + CST2 we can assert NAME2 >= -CST2
--- 5399,5413 ----
  						invert, &comp_code, &val))
      return;
  
!   /* Queue the assert.  */
!   tree x;
!   if (overflow_comparison_p (comp_code, name, val, false, &x))
!     {
!       enum tree_code new_code = ((comp_code == GT_EXPR || comp_code == GE_EXPR)
! 				 ? GT_EXPR : LE_EXPR);
!       add_assert_info (asserts, name, name, new_code, x);
      }
+   add_assert_info (asserts, name, name, comp_code, val);
  
    /* In the case of NAME <= CST and NAME being defined as
       NAME = (unsigned) NAME2 + CST2 we can assert NAME2 >= -CST2
*************** register_edge_assert_for_2 (tree name, e
*** 5423,5430 ****
        	  && TREE_CODE (name3) == SSA_NAME
  	  && (cst2 == NULL_TREE
  	      || TREE_CODE (cst2) == INTEGER_CST)
! 	  && INTEGRAL_TYPE_P (TREE_TYPE (name3))
! 	  && live_on_edge (e, name3))
  	{
  	  tree tmp;
  
--- 5447,5453 ----
        	  && TREE_CODE (name3) == SSA_NAME
  	  && (cst2 == NULL_TREE
  	      || TREE_CODE (cst2) == INTEGER_CST)
! 	  && INTEGRAL_TYPE_P (TREE_TYPE (name3)))
  	{
  	  tree tmp;
  
*************** register_edge_assert_for_2 (tree name, e
*** 5442,5456 ****
  	      fprintf (dump_file, "\n");
  	    }
  
! 	  register_new_assert_for (name3, tmp, comp_code, val, NULL, e, bsi);
  	}
  
        /* If name2 is used later, create an ASSERT_EXPR for it.  */
        if (name2 != NULL_TREE
        	  && TREE_CODE (name2) == SSA_NAME
  	  && TREE_CODE (cst2) == INTEGER_CST
! 	  && INTEGRAL_TYPE_P (TREE_TYPE (name2))
! 	  && live_on_edge (e, name2))
  	{
  	  tree tmp;
  
--- 5465,5478 ----
  	      fprintf (dump_file, "\n");
  	    }
  
! 	  add_assert_info (asserts, name3, tmp, comp_code, val);
  	}
  
        /* If name2 is used later, create an ASSERT_EXPR for it.  */
        if (name2 != NULL_TREE
        	  && TREE_CODE (name2) == SSA_NAME
  	  && TREE_CODE (cst2) == INTEGER_CST
! 	  && INTEGRAL_TYPE_P (TREE_TYPE (name2)))
  	{
  	  tree tmp;
  
*************** register_edge_assert_for_2 (tree name, e
*** 5470,5476 ****
  	      fprintf (dump_file, "\n");
  	    }
  
! 	  register_new_assert_for (name2, tmp, comp_code, val, NULL, e, bsi);
  	}
      }
  
--- 5492,5498 ----
  	      fprintf (dump_file, "\n");
  	    }
  
! 	  add_assert_info (asserts, name2, tmp, comp_code, val);
  	}
      }
  
*************** register_edge_assert_for_2 (tree name, e
*** 5496,5503 ****
  	    continue;
  
  	  tree name2 = gimple_assign_lhs (use_stmt);
! 	  if (TREE_CODE (name2) != SSA_NAME
! 	      || !live_on_edge (e, name2))
  	    continue;
  
  	  enum tree_code code = gimple_assign_rhs_code (use_stmt);
--- 5518,5524 ----
  	    continue;
  
  	  tree name2 = gimple_assign_lhs (use_stmt);
! 	  if (TREE_CODE (name2) != SSA_NAME)
  	    continue;
  
  	  enum tree_code code = gimple_assign_rhs_code (use_stmt);
*************** register_edge_assert_for_2 (tree name, e
*** 5525,5532 ****
  
  	  if (TREE_OVERFLOW_P (cst))
  	    cst = drop_tree_overflow (cst);
! 	  register_new_assert_for (name2, name2, comp_code, cst,
! 				   NULL, e, bsi);
  	}
      }
   
--- 5546,5552 ----
  
  	  if (TREE_OVERFLOW_P (cst))
  	    cst = drop_tree_overflow (cst);
! 	  add_assert_info (asserts, name2, name2, comp_code, cst);
  	}
      }
   
*************** register_edge_assert_for_2 (tree name, e
*** 5552,5566 ****
  	  tree op0 = gimple_assign_rhs1 (def_stmt);
  	  tree op1 = gimple_assign_rhs2 (def_stmt);
  	  if (TREE_CODE (op0) == SSA_NAME
! 	      && TREE_CODE (op1) == INTEGER_CST
! 	      && live_on_edge (e, op0))
  	    {
  	      enum tree_code reverse_op = (rhs_code == PLUS_EXPR
  					   ? MINUS_EXPR : PLUS_EXPR);
  	      op1 = int_const_binop (reverse_op, val, op1);
  	      if (TREE_OVERFLOW (op1))
  		op1 = drop_tree_overflow (op1);
! 	      register_new_assert_for (op0, op0, comp_code, op1, NULL, e, bsi);
  	    }
  	}
  
--- 5572,5585 ----
  	  tree op0 = gimple_assign_rhs1 (def_stmt);
  	  tree op1 = gimple_assign_rhs2 (def_stmt);
  	  if (TREE_CODE (op0) == SSA_NAME
! 	      && TREE_CODE (op1) == INTEGER_CST)
  	    {
  	      enum tree_code reverse_op = (rhs_code == PLUS_EXPR
  					   ? MINUS_EXPR : PLUS_EXPR);
  	      op1 = int_const_binop (reverse_op, val, op1);
  	      if (TREE_OVERFLOW (op1))
  		op1 = drop_tree_overflow (op1);
! 	      add_assert_info (asserts, op0, op0, comp_code, op1);
  	    }
  	}
  
*************** register_edge_assert_for_2 (tree name, e
*** 5578,5585 ****
  	      && prec == 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))
  	    {
  	      tree tmp, cst;
  	      enum tree_code new_comp_code = comp_code;
--- 5597,5603 ----
  	      && prec == TYPE_PRECISION (TREE_TYPE (name2))
  	      && (comp_code == LE_EXPR || comp_code == GT_EXPR
  		  || !tree_int_cst_equal (val,
! 					  TYPE_MIN_VALUE (TREE_TYPE (val)))))
  	    {
  	      tree tmp, cst;
  	      enum tree_code new_comp_code = comp_code;
*************** register_edge_assert_for_2 (tree name, e
*** 5606,5613 ****
  		  fprintf (dump_file, "\n");
  		}
  
! 	      register_new_assert_for (name2, tmp, new_comp_code, cst, NULL,
! 				       e, bsi);
  	    }
  	}
  
--- 5624,5630 ----
  		  fprintf (dump_file, "\n");
  		}
  
! 	      add_assert_info (asserts, name2, tmp, new_comp_code, cst);
  	    }
  	}
  
*************** register_edge_assert_for_2 (tree name, e
*** 5623,5630 ****
  	      && tree_fits_uhwi_p (cst2)
  	      && INTEGRAL_TYPE_P (TREE_TYPE (name2))
  	      && IN_RANGE (tree_to_uhwi (cst2), 1, prec - 1)
! 	      && prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val)))
! 	      && live_on_edge (e, name2))
  	    {
  	      mask = wi::mask (tree_to_uhwi (cst2), false, prec);
  	      val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2);
--- 5640,5646 ----
  	      && tree_fits_uhwi_p (cst2)
  	      && INTEGRAL_TYPE_P (TREE_TYPE (name2))
  	      && IN_RANGE (tree_to_uhwi (cst2), 1, prec - 1)
! 	      && prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val))))
  	    {
  	      mask = wi::mask (tree_to_uhwi (cst2), false, prec);
  	      val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2);
*************** register_edge_assert_for_2 (tree name, e
*** 5682,5689 ****
  		  fprintf (dump_file, "\n");
  		}
  
! 	      register_new_assert_for (name2, tmp, new_comp_code, new_val,
! 				       NULL, e, bsi);
  	    }
  	}
  
--- 5698,5704 ----
  		  fprintf (dump_file, "\n");
  		}
  
! 	      add_assert_info (asserts, name2, tmp, new_comp_code, new_val);
  	    }
  	}
  
*************** register_edge_assert_for_2 (tree name, e
*** 5728,5739 ****
  		  if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
  		      || !INTEGRAL_TYPE_P (TREE_TYPE (names[1]))
  		      || (TYPE_PRECISION (TREE_TYPE (name2))
! 			  != TYPE_PRECISION (TREE_TYPE (names[1])))
! 		      || !live_on_edge (e, names[1]))
  		    names[1] = NULL_TREE;
  		}
! 	      if (live_on_edge (e, name2))
! 		names[0] = name2;
  	    }
  	}
        if (names[0] || names[1])
--- 5743,5752 ----
  		  if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
  		      || !INTEGRAL_TYPE_P (TREE_TYPE (names[1]))
  		      || (TYPE_PRECISION (TREE_TYPE (name2))
! 			  != TYPE_PRECISION (TREE_TYPE (names[1]))))
  		    names[1] = NULL_TREE;
  		}
! 	      names[0] = name2;
  	    }
  	}
        if (names[0] || names[1])
*************** register_edge_assert_for_2 (tree name, e
*** 5924,5931 ****
  			fprintf (dump_file, "\n");
  		      }
  
! 		    register_new_assert_for (names[i], tmp, LE_EXPR,
! 					     new_val, NULL, e, bsi);
  		  }
  	    }
  	}
--- 5937,5943 ----
  			fprintf (dump_file, "\n");
  		      }
  
! 		    add_assert_info (asserts, names[i], tmp, LE_EXPR, new_val);
  		  }
  	    }
  	}
*************** register_edge_assert_for_2 (tree name, e
*** 5941,5947 ****
  
  static void
  register_edge_assert_for_1 (tree op, enum tree_code code,
! 			    edge e, gimple_stmt_iterator bsi)
  {
    gimple *op_def;
    tree val;
--- 5953,5959 ----
  
  static void
  register_edge_assert_for_1 (tree op, enum tree_code code,
! 			    edge e, vec<assert_info> &asserts)
  {
    gimple *op_def;
    tree val;
*************** register_edge_assert_for_1 (tree op, enu
*** 5951,5963 ****
    if (TREE_CODE (op) != SSA_NAME)
      return;
  
!   /* We know that OP will have a zero or nonzero value.  If OP is used
!      more than once go ahead and register an assert for OP.  */
!   if (live_on_edge (e, op))
!     {
!       val = build_int_cst (TREE_TYPE (op), 0);
!       register_new_assert_for (op, op, code, val, NULL, e, bsi);
!     }
  
    /* Now look at how OP is set.  If it's set from a comparison,
       a truth operation or some bit operations, then we may be able
--- 5963,5971 ----
    if (TREE_CODE (op) != SSA_NAME)
      return;
  
!   /* We know that OP will have a zero or nonzero value.  */
!   val = build_int_cst (TREE_TYPE (op), 0);
!   add_assert_info (asserts, op, op, code, val);
  
    /* Now look at how OP is set.  If it's set from a comparison,
       a truth operation or some bit operations, then we may be able
*************** register_edge_assert_for_1 (tree op, enu
*** 5975,5983 ****
        tree op1 = gimple_assign_rhs2 (op_def);
  
        if (TREE_CODE (op0) == SSA_NAME)
!         register_edge_assert_for_2 (op0, e, bsi, rhs_code, op0, op1, invert);
        if (TREE_CODE (op1) == SSA_NAME)
!         register_edge_assert_for_2 (op1, e, bsi, rhs_code, op0, op1, invert);
      }
    else if ((code == NE_EXPR
  	    && gimple_assign_rhs_code (op_def) == BIT_AND_EXPR)
--- 5983,5991 ----
        tree op1 = gimple_assign_rhs2 (op_def);
  
        if (TREE_CODE (op0) == SSA_NAME)
!         register_edge_assert_for_2 (op0, e, rhs_code, op0, op1, invert, asserts);
        if (TREE_CODE (op1) == SSA_NAME)
!         register_edge_assert_for_2 (op1, e, rhs_code, op0, op1, invert, asserts);
      }
    else if ((code == NE_EXPR
  	    && gimple_assign_rhs_code (op_def) == BIT_AND_EXPR)
*************** register_edge_assert_for_1 (tree op, enu
*** 5989,6010 ****
        tree op1 = gimple_assign_rhs2 (op_def);
        if (TREE_CODE (op0) == SSA_NAME
  	  && has_single_use (op0))
! 	register_edge_assert_for_1 (op0, code, e, bsi);
        if (TREE_CODE (op1) == SSA_NAME
  	  && has_single_use (op1))
! 	register_edge_assert_for_1 (op1, code, e, bsi);
      }
    else if (gimple_assign_rhs_code (op_def) == BIT_NOT_EXPR
  	   && TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (op_def))) == 1)
      {
        /* Recurse, flipping CODE.  */
        code = invert_tree_comparison (code, false);
!       register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, bsi);
      }
    else if (gimple_assign_rhs_code (op_def) == SSA_NAME)
      {
        /* Recurse through the copy.  */
!       register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, bsi);
      }
    else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (op_def)))
      {
--- 5997,6018 ----
        tree op1 = gimple_assign_rhs2 (op_def);
        if (TREE_CODE (op0) == SSA_NAME
  	  && has_single_use (op0))
! 	register_edge_assert_for_1 (op0, code, e, asserts);
        if (TREE_CODE (op1) == SSA_NAME
  	  && has_single_use (op1))
! 	register_edge_assert_for_1 (op1, code, e, asserts);
      }
    else if (gimple_assign_rhs_code (op_def) == BIT_NOT_EXPR
  	   && TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (op_def))) == 1)
      {
        /* Recurse, flipping CODE.  */
        code = invert_tree_comparison (code, false);
!       register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, asserts);
      }
    else if (gimple_assign_rhs_code (op_def) == SSA_NAME)
      {
        /* Recurse through the copy.  */
!       register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, asserts);
      }
    else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (op_def)))
      {
*************** register_edge_assert_for_1 (tree op, enu
*** 6014,6020 ****
        if (INTEGRAL_TYPE_P (TREE_TYPE (rhs))
  	  && (TYPE_PRECISION (TREE_TYPE (rhs))
  	      <= TYPE_PRECISION (TREE_TYPE (op))))
! 	register_edge_assert_for_1 (rhs, code, e, bsi);
      }
  }
  
--- 6022,6028 ----
        if (INTEGRAL_TYPE_P (TREE_TYPE (rhs))
  	  && (TYPE_PRECISION (TREE_TYPE (rhs))
  	      <= TYPE_PRECISION (TREE_TYPE (op))))
! 	register_edge_assert_for_1 (rhs, code, e, asserts);
      }
  }
  
*************** register_edge_assert_for_1 (tree op, enu
*** 6023,6031 ****
     SI.  */
  
  static void
! register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
  			  enum tree_code cond_code, tree cond_op0,
! 			  tree cond_op1)
  {
    tree val;
    enum tree_code comp_code;
--- 6031,6039 ----
     SI.  */
  
  static void
! register_edge_assert_for (tree name, edge e,
  			  enum tree_code cond_code, tree cond_op0,
! 			  tree cond_op1, vec<assert_info> &asserts)
  {
    tree val;
    enum tree_code comp_code;
*************** register_edge_assert_for (tree name, edg
*** 6043,6050 ****
      return;
  
    /* Register ASSERT_EXPRs for name.  */
!   register_edge_assert_for_2 (name, e, si, cond_code, cond_op0,
! 			      cond_op1, is_else_edge);
  
  
    /* If COND is effectively an equality test of an SSA_NAME against
--- 6051,6058 ----
      return;
  
    /* Register ASSERT_EXPRs for name.  */
!   register_edge_assert_for_2 (name, e, cond_code, cond_op0,
! 			      cond_op1, is_else_edge, asserts);
  
  
    /* If COND is effectively an equality test of an SSA_NAME against
*************** register_edge_assert_for (tree name, edg
*** 6064,6071 ****
  	{
  	  tree op0 = gimple_assign_rhs1 (def_stmt);
  	  tree op1 = gimple_assign_rhs2 (def_stmt);
! 	  register_edge_assert_for_1 (op0, NE_EXPR, e, si);
! 	  register_edge_assert_for_1 (op1, NE_EXPR, e, si);
  	}
      }
  
--- 6072,6079 ----
  	{
  	  tree op0 = gimple_assign_rhs1 (def_stmt);
  	  tree op1 = gimple_assign_rhs2 (def_stmt);
! 	  register_edge_assert_for_1 (op0, NE_EXPR, e, asserts);
! 	  register_edge_assert_for_1 (op1, NE_EXPR, e, asserts);
  	}
      }
  
*************** register_edge_assert_for (tree name, edg
*** 6086,6097 ****
  	{
  	  tree op0 = gimple_assign_rhs1 (def_stmt);
  	  tree op1 = gimple_assign_rhs2 (def_stmt);
! 	  register_edge_assert_for_1 (op0, EQ_EXPR, e, si);
! 	  register_edge_assert_for_1 (op1, EQ_EXPR, e, si);
  	}
      }
  }
  
  
  /* Determine whether the outgoing edges of BB should receive an
     ASSERT_EXPR for each of the operands of BB's LAST statement.
--- 6094,6121 ----
  	{
  	  tree op0 = gimple_assign_rhs1 (def_stmt);
  	  tree op1 = gimple_assign_rhs2 (def_stmt);
! 	  register_edge_assert_for_1 (op0, EQ_EXPR, e, asserts);
! 	  register_edge_assert_for_1 (op1, EQ_EXPR, e, asserts);
  	}
      }
  }
  
+ /* Finish found ASSERTS for E and register them at GSI.  */
+ 
+ static void
+ finish_register_edge_assert_for (edge e, gimple_stmt_iterator gsi,
+ 				 vec<assert_info> &asserts)
+ {
+   for (unsigned i = 0; i < asserts.length (); ++i)
+     /* Only register an ASSERT_EXPR if NAME was found in the sub-graph
+        reachable from E.  */
+     if (live_on_edge (e, asserts[i].name))
+       register_new_assert_for (asserts[i].name, asserts[i].expr,
+ 			       asserts[i].comp_code, asserts[i].val,
+ 			       NULL, e, gsi);
+ }
+ 
+ 
  
  /* Determine whether the outgoing edges of BB should receive an
     ASSERT_EXPR for each of the operands of BB's LAST statement.
*************** find_conditional_asserts (basic_block bb
*** 6123,6133 ****
  
        /* Register the necessary assertions for each operand in the
  	 conditional predicate.  */
        FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
! 	register_edge_assert_for (op, e, bsi,
  				  gimple_cond_code (last),
  				  gimple_cond_lhs (last),
! 				  gimple_cond_rhs (last));
      }
  }
  
--- 6147,6159 ----
  
        /* Register the necessary assertions for each operand in the
  	 conditional predicate.  */
+       auto_vec<assert_info, 8> asserts;
        FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
! 	register_edge_assert_for (op, e,
  				  gimple_cond_code (last),
  				  gimple_cond_lhs (last),
! 				  gimple_cond_rhs (last), asserts);
!       finish_register_edge_assert_for (e, bsi, asserts);
      }
  }
  
*************** find_switch_asserts (basic_block bb, gsw
*** 6239,6250 ****
  
        /* Register the necessary assertions for the operand in the
  	 SWITCH_EXPR.  */
!       register_edge_assert_for (op, e, bsi,
  				max ? GE_EXPR : EQ_EXPR,
! 				op, fold_convert (TREE_TYPE (op), min));
        if (max)
! 	register_edge_assert_for (op, e, bsi, LE_EXPR, op,
! 				  fold_convert (TREE_TYPE (op), max));
      }
  
    XDELETEVEC (ci);
--- 6265,6280 ----
  
        /* Register the necessary assertions for the operand in the
  	 SWITCH_EXPR.  */
!       auto_vec<assert_info, 8> asserts;
!       register_edge_assert_for (op, e,
  				max ? GE_EXPR : EQ_EXPR,
! 				op, fold_convert (TREE_TYPE (op), min),
! 				asserts);
        if (max)
! 	register_edge_assert_for (op, e, LE_EXPR, op,
! 				  fold_convert (TREE_TYPE (op), max),
! 				  asserts);
!       finish_register_edge_assert_for (e, bsi, asserts);
      }
  
    XDELETEVEC (ci);
*************** find_switch_asserts (basic_block bb, gsw
*** 6293,6300 ****
        if (max == NULL_TREE)
  	{
  	  /* Register the assertion OP != MIN.  */
  	  min = fold_convert (TREE_TYPE (op), min);
! 	  register_edge_assert_for (op, default_edge, bsi, NE_EXPR, op, min);
  	}
        else
  	{
--- 6323,6333 ----
        if (max == NULL_TREE)
  	{
  	  /* Register the assertion OP != MIN.  */
+ 	  auto_vec<assert_info, 8> asserts;
  	  min = fold_convert (TREE_TYPE (op), min);
! 	  register_edge_assert_for (op, default_edge, NE_EXPR, op, min,
! 				    asserts);
! 	  finish_register_edge_assert_for (default_edge, bsi, asserts);
  	}
        else
  	{
*************** public:
*** 11160,11166 ****
    virtual void after_dom_children (basic_block);
    void push_value_range (tree var, value_range *vr);
    value_range *pop_value_range (tree var);
!   value_range *try_find_new_range (tree op, tree_code code, tree limit);
  
    /* Cond_stack holds the old VR.  */
    auto_vec<std::pair <tree, value_range*> > stack;
--- 11203,11209 ----
    virtual void after_dom_children (basic_block);
    void push_value_range (tree var, value_range *vr);
    value_range *pop_value_range (tree var);
!   value_range *try_find_new_range (tree, tree op, tree_code code, tree limit);
  
    /* Cond_stack holds the old VR.  */
    auto_vec<std::pair <tree, value_range*> > stack;
*************** public:
*** 11169,11187 ****
    auto_vec<gimple *> stmts_to_remove;
  };
  
! /*  Find new range for OP such that (OP CODE LIMIT) is true.  */
  
  value_range *
! evrp_dom_walker::try_find_new_range (tree op, tree_code code, tree limit)
  {
    value_range vr = VR_INITIALIZER;
!   value_range *old_vr = get_value_range (op);
  
    /* Discover VR when condition is true.  */
!   extract_range_for_var_from_comparison_expr (op, code, op,
  					      limit, &vr);
-   if (old_vr->type == VR_RANGE || old_vr->type == VR_ANTI_RANGE)
-     vrp_intersect_ranges (&vr, old_vr);
    /* If we found any usable VR, set the VR to ssa_name and create a
       PUSH old value in the stack with the old VR.  */
    if (vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)
--- 11212,11229 ----
    auto_vec<gimple *> stmts_to_remove;
  };
  
! /*  Find new range for NAME such that (OP CODE LIMIT) is true.  */
  
  value_range *
! evrp_dom_walker::try_find_new_range (tree name,
! 				     tree op, tree_code code, tree limit)
  {
    value_range vr = VR_INITIALIZER;
!   value_range *old_vr = get_value_range (name);
  
    /* Discover VR when condition is true.  */
!   extract_range_for_var_from_comparison_expr (name, code, op,
  					      limit, &vr);
    /* If we found any usable VR, set the VR to ssa_name and create a
       PUSH old value in the stack with the old VR.  */
    if (vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)
*************** evrp_dom_walker::before_dom_children (ba
*** 11245,11280 ****
  	  /* Entering a new scope.  Try to see if we can find a VR
  	     here.  */
  	  tree op1 = gimple_cond_rhs (stmt);
- 	  tree_code code = gimple_cond_code (stmt);
- 
  	  if (TREE_OVERFLOW_P (op1))
  	    op1 = drop_tree_overflow (op1);
  
! 	  /* If condition is false, invert the cond.  */
! 	  if (pred_e->flags & EDGE_FALSE_VALUE)
! 	    code = invert_tree_comparison (gimple_cond_code (stmt),
! 					   HONOR_NANS (op0));
! 	  /* Add VR when (OP0 CODE OP1) condition is true.  */
! 	  value_range *op0_range = try_find_new_range (op0, code, op1);
! 
! 	  /* Register ranges for y in x < y where
! 	     y might have ranges that are useful.  */
! 	  tree limit;
! 	  tree_code new_code;
! 	  if (TREE_CODE (op1) == SSA_NAME
! 	      && extract_code_and_val_from_cond_with_ops (op1, code,
! 							  op0, op1,
! 							  false,
! 							  &new_code, &limit))
! 	    {
! 	      /* Add VR when (OP1 NEW_CODE LIMIT) condition is true.  */
! 	      value_range *op1_range = try_find_new_range (op1, new_code, limit);
! 	      if (op1_range)
! 		push_value_range (op1, op1_range);
! 	    }
! 
! 	  if (op0_range)
! 	    push_value_range (op0, op0_range);
  	}
      }
  
--- 11287,11315 ----
  	  /* Entering a new scope.  Try to see if we can find a VR
  	     here.  */
  	  tree op1 = gimple_cond_rhs (stmt);
  	  if (TREE_OVERFLOW_P (op1))
  	    op1 = drop_tree_overflow (op1);
+ 	  tree_code code = gimple_cond_code (stmt);
  
! 	  auto_vec<assert_info, 8> asserts;
! 	  register_edge_assert_for (op0, pred_e, code, op0, op1, asserts);
! 	  if (TREE_CODE (op1) == SSA_NAME)
! 	    register_edge_assert_for (op1, pred_e, code, op0, op1, asserts);
! 
! 	  auto_vec<std::pair<tree, value_range *>, 8> vrs;
! 	  for (unsigned i = 0; i < asserts.length (); ++i)
! 	    {
! 	      value_range *vr = try_find_new_range (asserts[i].name,
! 						    asserts[i].expr,
! 						    asserts[i].comp_code,
! 						    asserts[i].val);
! 	      if (vr)
! 		vrs.safe_push (std::make_pair (asserts[i].name, vr));
! 	    }
! 	  /* Push updated ranges only after finding all of them to avoid
! 	     ordering issues that can lead to worse ranges.  */
! 	  for (unsigned i = 0; i < vrs.length (); ++i)
! 	    push_value_range (vrs[i].first, vrs[i].second);
  	}
      }
  
*************** evrp_dom_walker::before_dom_children (ba
*** 11462,11474 ****
  		      /* Add VR when (T COMP_CODE value) condition is
  			 true.  */
  		      value_range *op_range
! 			= try_find_new_range (t, comp_code, value);
  		      if (op_range)
  			push_value_range (t, op_range);
  		    }
  		}
  	      /* Add VR when (OP COMP_CODE value) condition is true.  */
! 	      value_range *op_range = try_find_new_range (op,
  							  comp_code, value);
  	      if (op_range)
  		push_value_range (op, op_range);
--- 11497,11509 ----
  		      /* Add VR when (T COMP_CODE value) condition is
  			 true.  */
  		      value_range *op_range
! 			= try_find_new_range (t, t, comp_code, value);
  		      if (op_range)
  			push_value_range (t, op_range);
  		    }
  		}
  	      /* Add VR when (OP COMP_CODE value) condition is true.  */
! 	      value_range *op_range = try_find_new_range (op, op,
  							  comp_code, value);
  	      if (op_range)
  		push_value_range (op, op_range);
Index: gcc/testsuite/gcc.dg/tree-ssa/evrp7.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/evrp7.c	(nonexistent)
--- gcc/testsuite/gcc.dg/tree-ssa/evrp7.c	(working copy)
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-evrp-details" } */
+ 
+ int test1(int i, int k)
+ {
+   if (i > 0 && i <= 5 && k >= 10 && k < 42)
+     {
+       int j = i + 1 + k;
+       return j == 10;
+     }
+   return 1;
+ }
+ 
+ /* { dg-final { scan-tree-dump "Removing dead stmt \[^\r\n\]* = j_.* == 10" "evrp" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/evrp8.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/evrp8.c	(nonexistent)
--- gcc/testsuite/gcc.dg/tree-ssa/evrp8.c	(working copy)
***************
*** 0 ****
--- 1,11 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-evrp-details" } */
+ 
+ int foo(int i)
+ {
+   if (i < 0 || i >= 5)
+     return i == 1;
+   return 1;
+ }
+ 
+ /* { dg-final { scan-tree-dump "Removing dead stmt \[^\r\n\]* = i_.* == 1" "evrp" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/evrp9.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/evrp9.c	(nonexistent)
--- gcc/testsuite/gcc.dg/tree-ssa/evrp9.c	(working copy)
***************
*** 0 ****
--- 1,28 ----
+ /* PR tree-optimization/49039 */
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-evrp" } */
+ 
+ extern void bar (void);
+ 
+ void
+ foo (unsigned int x, unsigned int y)
+ {
+   unsigned int minv, maxv;
+   if (x >= 3 && x <= 6)
+     return;
+   if (y >= 5 && y <= 8)
+     return;
+   minv = x < y ? x : y;
+   maxv = x > y ? x : y;
+   if (minv == 5)
+     bar ();
+   if (minv == 6)
+     bar ();
+   if (maxv == 5)
+     bar ();
+   if (maxv == 6)
+     bar ();
+ }
+ 
+ /* { dg-final { scan-tree-dump-not "== 5" "evrp" } } */
+ /* { dg-final { scan-tree-dump-not "== 6" "evrp" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/vrp35.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/vrp35.c	(revision 247293)
--- gcc/testsuite/gcc.dg/tree-ssa/vrp35.c	(working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-vrp1-details" } */
  
  int test1(int i, int k)
  {
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1-details" } */
  
  int test1(int i, int k)
  {
Index: gcc/testsuite/gcc.dg/tree-ssa/vrp36.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/vrp36.c	(revision 247293)
--- gcc/testsuite/gcc.dg/tree-ssa/vrp36.c	(working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-vrp1-details" } */
  
  int foo(int i)
  {
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1-details" } */
  
  int foo(int i)
  {
Index: gcc/testsuite/gcc.dg/tree-ssa/pr49039.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/pr49039.c	(revision 247293)
--- gcc/testsuite/gcc.dg/tree-ssa/pr49039.c	(working copy)
***************
*** 1,6 ****
  /* PR tree-optimization/49039 */
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-vrp1" } */
  
  extern void bar (void);
  
--- 1,6 ----
  /* PR tree-optimization/49039 */
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1" } */
  
  extern void bar (void);
  



More information about the Gcc-patches mailing list