public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Kugan <kugan.vivekanandarajah@linaro.org>
To: Richard Biener <richard.guenther@gmail.com>
Cc: Uros Bizjak <ubizjak@gmail.com>,
	 "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>,
	Jakub Jelinek <jakub@redhat.com>
Subject: Re: [PATCH 2/2] Enable elimination of zext/sext
Date: Thu, 04 Sep 2014 03:41:00 -0000	[thread overview]
Message-ID: <5407DF57.2040902@linaro.org> (raw)
In-Reply-To: <CAFiYyc2-Z6TpJfMbkRF2eki=qoCjJywzR1gJZKX9oZ+bh0enow@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2196 bytes --]

>> I added this part of the code (in cfgexpand.c) to handle binary/unary/..
>> gimple operations and used the LHS value range to infer the assigned
>> value range. I will revert this part of the code as this is wrong.
>>
>> I dont think checking promoted_mode for temp will be necessary here as
>> convert_move will handle it correctly if promoted_mode is set for temp.
>>
>> Thus, I will reimplement setting promoted_mode to temp (in
>> expand_expr_real_2) based on the gimple statement content on RHS. i.e.
>> by looking at the RHS operands and its value ranges and by calculating
>> the resulting value range. Does this sound OK to you.
> 
> No, this sounds backward again and won't work because those operands
> again could be just truncated - thus you can't rely on their value-range.
> 
> What you would need is VRP computing value-ranges in the promoted
> mode from the start (and it doesn't do that).


Hi Richard,

Here is an attempt to do the value range computation in promoted_mode's
type when it is overflowing. Bootstrapped on x86-84.

Based on your feedback, I will do more testing on this.

Thanks for your time,
Kugan

gcc/ChangeLog:

2014-09-04  Kugan Vivekanandarajah <kuganv@linaro.org>

	* tree-ssa-ccp.c (ccp_finalize): Adjust the nonzero_bits precision to
	the type.
	(evaluate_stmt): Likewise.
	* tree-ssanames.c (set_range_info): Adjust if the precision of stored
	value range is different.
	* tree-vrp.c (normalize_int_cst_precision): New function.
	(set_value_range): Add assert to check precision.
	(set_and_canonicalize_value_range): Call normalize_int_cst_precision
	on min and max.
	(promoted_type): New function.
	(promote_unary_vr): Likewise.
	(promote_binary_vr): Likewise.
	(extract_range_from_binary_expr_1): Adjust type to match value range.
	Store value ranges in promoted type if they overflow.
	(extract_range_from_unary_expr_1): Likewise.
	(adjust_range_with_scev): Call normalize_int_cst_precision
	on min and max.
	(vrp_visit_assignment_or_call): Likewise.
	(simplify_bit_ops_using_ranges): Adjust the value range precision.
	(test_for_singularity): Likewise.
	(simplify_stmt_for_jump_threading): Likewise.
	(extract_range_from_assert): Likewise.

[-- Attachment #2: p.txt --]
[-- Type: text/plain, Size: 13120 bytes --]

diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index a90f708..1733073 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -916,7 +916,11 @@ ccp_finalize (void)
 	  unsigned int precision = TYPE_PRECISION (TREE_TYPE (val->value));
 	  wide_int nonzero_bits = wide_int::from (val->mask, precision,
 						  UNSIGNED) | val->value;
-	  nonzero_bits &= get_nonzero_bits (name);
+	  wide_int nonzero_bits_name = get_nonzero_bits (name);
+	  if (precision != nonzero_bits_name.get_precision ())
+	    nonzero_bits = wi::shwi (*nonzero_bits.get_val (),
+				     nonzero_bits_name.get_precision ());
+	  nonzero_bits &= nonzero_bits_name;
 	  set_nonzero_bits (name, nonzero_bits);
 	}
     }
@@ -1852,6 +1856,8 @@ evaluate_stmt (gimple stmt)
     {
       tree lhs = gimple_get_lhs (stmt);
       wide_int nonzero_bits = get_nonzero_bits (lhs);
+      if (TYPE_PRECISION (TREE_TYPE (lhs)) != nonzero_bits.get_precision ())
+	  nonzero_bits = wide_int_to_tree (TREE_TYPE (lhs), nonzero_bits);
       if (nonzero_bits != -1)
 	{
 	  if (!is_constant)
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 3af80a0..459c669 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -192,7 +192,7 @@ set_range_info (tree name, enum value_range_type range_type,
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
-  unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
+  unsigned int precision = min.get_precision ();
 
   /* Allocate if not available.  */
   if (ri == NULL)
@@ -204,6 +204,15 @@ set_range_info (tree name, enum value_range_type range_type,
       SSA_NAME_RANGE_INFO (name) = ri;
       ri->set_nonzero_bits (wi::shwi (-1, precision));
     }
+  else if (ri->get_min ().get_precision () != precision)
+    {
+      size_t size = (sizeof (range_info_def)
+		     + trailing_wide_ints <3>::extra_size (precision));
+      ri = static_cast<range_info_def *> (ggc_realloc (ri, size));
+      ri->ints.set_precision (precision);
+      SSA_NAME_RANGE_INFO (name) = ri;
+      ri->set_nonzero_bits (wi::shwi (-1, precision));
+    }
 
   /* Record the range type.  */
   if (SSA_NAME_RANGE_TYPE (name) != range_type)
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index d16fd8a..772676a 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "optabs.h"
 #include "tree-ssa-threadedge.h"
 #include "wide-int.h"
+#include "langhooks.h"
 
 
 
@@ -424,6 +425,23 @@ set_value_range_to_varying (value_range_t *vr)
     bitmap_clear (vr->equiv);
 }
 
+/* Normalize min and max to promoted_type if their precision differs.  */
+
+static void
+normalize_int_cst_precision (tree *min, tree *max)
+{
+  if (TREE_CODE (*min) != INTEGER_CST
+	      || TREE_CODE (*max) != INTEGER_CST)
+    return;
+  if (TYPE_PRECISION (TREE_TYPE (*min)) != TYPE_PRECISION (TREE_TYPE (*max)))
+    {
+      tree type = TREE_TYPE (*min);
+      if (TYPE_PRECISION (TREE_TYPE (*min)) < TYPE_PRECISION (TREE_TYPE (*max)))
+	type = TREE_TYPE (*max);
+      *min = wide_int_to_tree (type, *min);
+      *max = wide_int_to_tree (type, *max);
+    }
+}
 
 /* Set value range VR to {T, MIN, MAX, EQUIV}.  */
 
@@ -438,6 +456,8 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min,
       int cmp;
 
       gcc_assert (min && max);
+      gcc_assert (TYPE_PRECISION (TREE_TYPE (min))
+		  == TYPE_PRECISION (TREE_TYPE (max)));
 
       gcc_assert ((!TREE_OVERFLOW_P (min) || is_overflow_infinity (min))
 		  && (!TREE_OVERFLOW_P (max) || is_overflow_infinity (max)));
@@ -597,6 +617,8 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
       return;
     }
 
+  if (min != NULL_TREE && max != NULL_TREE)
+    normalize_int_cst_precision (&min, &max);
   set_value_range (vr, t, min, max, equiv);
 }
 
@@ -951,6 +973,66 @@ usable_range_p (value_range_t *vr, bool *strict_overflow_p)
   return true;
 }
 
+/* Return the promoted type as defined by PROMOTE_MODE of the target.  */
+
+static tree
+promoted_type (tree type)
+{
+#ifdef PROMOTE_MODE
+  tree new_type;
+  if (!POINTER_TYPE_P (type)
+      && (TREE_CODE (type) != ENUMERAL_TYPE)
+      && INTEGRAL_TYPE_P (type))
+    {
+      enum machine_mode mode = TYPE_MODE (type);
+      int uns = TYPE_SIGN (type);
+      PROMOTE_MODE (mode, uns, type);
+      uns = TYPE_SIGN (type);
+      new_type = lang_hooks.types.type_for_mode (mode, uns);
+      if (TYPE_PRECISION (new_type) > TYPE_PRECISION (type))
+	type = new_type;
+    }
+#endif
+  return type;
+}
+
+/* Promote VRO to promoted_type if their precision differ and
+   return the new type.  */
+
+static tree
+promote_unary_vr (tree type, value_range_t *vr0)
+{
+  tree expr_type = type;
+
+  if (!range_int_cst_p (vr0))
+    return expr_type;
+  if ((TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (vr0->min)))
+      || (TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (vr0->max))))
+    {
+      expr_type = promoted_type (type);
+      vr0->min = wide_int_to_tree (expr_type, vr0->min);
+      vr0->max = wide_int_to_tree (expr_type, vr0->max);
+    }
+  return expr_type;
+}
+
+/* Promote VRO and VR1 to promoted_type if their precision differ and
+   return the new type.  */
+
+static tree
+promote_binary_vr (tree type, value_range_t *vr0, value_range_t *vr1)
+{
+  tree expr_type0 = promote_unary_vr (type, vr0);
+  tree expr_type1 = promote_unary_vr (type, vr1);
+
+  if (TYPE_PRECISION (expr_type0) == TYPE_PRECISION (expr_type1))
+    return expr_type0;
+  if (TYPE_PRECISION (expr_type0) < TYPE_PRECISION (expr_type1))
+    return promote_unary_vr (expr_type1, vr0);
+  else
+    return promote_unary_vr (expr_type0, vr1);
+}
+
 
 /* Return true if the result of assignment STMT is know to be non-negative.
    If the return value is based on the assumption that signed overflow is
@@ -1741,6 +1823,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
 		TREE_NO_WARNING (max) = 1;
 	    }
 
+	  normalize_int_cst_precision (&min, &max);
 	  set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
 	}
     }
@@ -1781,6 +1864,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
 		TREE_NO_WARNING (min) = 1;
 	    }
 
+	  normalize_int_cst_precision (&min, &max);
 	  set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
 	}
     }
@@ -2376,6 +2460,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
      range and see what we end up with.  */
   if (code == PLUS_EXPR || code == MINUS_EXPR)
     {
+      /* If any of the value range is in promoted type, promote them all
+	 including the type.  */
+      expr_type = promote_binary_vr (expr_type, &vr0, &vr1);
       /* If we have a PLUS_EXPR with two VR_RANGE integer constant
          ranges compute the precise range for such case if possible.  */
       if (range_int_cst_p (&vr0)
@@ -2562,6 +2649,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   else if (code == MIN_EXPR
 	   || code == MAX_EXPR)
     {
+      /* If any of the value range is in promoted type, promote them all
+	 including the type.  */
+      expr_type = promote_binary_vr (expr_type, &vr0, &vr1);
       if (vr0.type == VR_RANGE
 	  && !symbolic_range_p (&vr0))
 	{
@@ -2625,6 +2715,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
              <wi::extended_tree <WIDE_INT_MAX_PRECISION * 2> > vrp_int_cst;
 	  vrp_int sizem1 = wi::mask <vrp_int> (prec, false);
 	  vrp_int size = sizem1 + 1;
+	  vrp_int type_min = vrp_int_cst (TYPE_MIN_VALUE (expr_type));
+	  vrp_int type_max = vrp_int_cst (TYPE_MAX_VALUE (expr_type));
 
 	  /* Extend the values using the sign of the result to PREC2.
 	     From here on out, everthing is just signed math no matter
@@ -2697,8 +2789,17 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 
 	  /* The following should handle the wrapping and selecting
 	     VR_ANTI_RANGE for us.  */
-	  min = wide_int_to_tree (expr_type, prod0);
-	  max = wide_int_to_tree (expr_type, prod3);
+	  if (wi::lts_p (prod0, type_min)
+	      || wi::gts_p (prod3, type_max))
+	    {
+	      min = wide_int_to_tree (promoted_type (expr_type), prod0);
+	      max = wide_int_to_tree (promoted_type (expr_type), prod3);
+	    }
+	  else
+	    {
+	      min = wide_int_to_tree (expr_type, prod0);
+	      max = wide_int_to_tree (expr_type, prod3);
+	    }
 	  set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
 	  return;
 	}
@@ -2724,6 +2825,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   else if (code == RSHIFT_EXPR
 	   || code == LSHIFT_EXPR)
     {
+      /* If value range is in promoted type, promote the type as well.  */
+      expr_type = promote_unary_vr (expr_type, &vr0);
       /* If we have a RSHIFT_EXPR with any shift values outside [0..prec-1],
 	 then drop to VR_VARYING.  Outside of this range we get undefined
 	 behavior from the shift operation.  We cannot even trust
@@ -2946,6 +3049,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       wide_int may_be_nonzero0, may_be_nonzero1;
       wide_int must_be_nonzero0, must_be_nonzero1;
 
+      /* If any of the value range is in promoted type, promote them all
+	 including the type.  */
+      expr_type = promote_binary_vr (expr_type, &vr0, &vr1);
       int_cst_range0 = zero_nonzero_bits_from_vr (expr_type, &vr0,
 						  &may_be_nonzero0,
 						  &must_be_nonzero0);
@@ -3224,14 +3330,22 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
 	  tree new_min, new_max;
 	  if (is_overflow_infinity (vr0.min))
 	    new_min = negative_overflow_infinity (outer_type);
-	  else
+	  else if (int_fits_type_p (vr0.min, outer_type))
 	    new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
 				      0, false);
+	  else
+	    new_min = force_fit_type (promoted_type (outer_type),
+				      wi::to_widest (vr0.min),
+				      0, false);
 	  if (is_overflow_infinity (vr0.max))
 	    new_max = positive_overflow_infinity (outer_type);
-	  else
+	  else if (int_fits_type_p (vr0.min, outer_type))
 	    new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
 				      0, false);
+	  else
+	    new_max = force_fit_type (promoted_type (outer_type),
+				      wi::to_widest (vr0.max),
+				      0, false);
 	  set_and_canonicalize_value_range (vr, vr0.type,
 					    new_min, new_max, NULL);
 	  return;
@@ -3940,6 +4054,8 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
 	  && is_positive_overflow_infinity (max)))
     return;
 
+  if (min != NULL_TREE && max != NULL_TREE)
+    normalize_int_cst_precision (&min, &max);
   set_value_range (vr, VR_RANGE, min, max, vr->equiv);
 }
 
@@ -6668,6 +6784,8 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
       else
 	extract_range_from_assignment (&new_vr, stmt);
 
+      if (range_int_cst_p (&new_vr))
+	normalize_int_cst_precision (&new_vr.min, &new_vr.max);
       if (update_value_range (lhs, &new_vr))
 	{
 	  *output_p = lhs;
@@ -8399,6 +8517,8 @@ vrp_visit_phi_node (gimple phi)
   /* If the new range is different than the previous value, keep
      iterating.  */
 update_range:
+  if (range_int_cst_p (&vr_result))
+    normalize_int_cst_precision (&vr_result.min, &vr_result.max);
   if (update_value_range (lhs, &vr_result))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -8655,9 +8775,19 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   if (!zero_nonzero_bits_from_vr (TREE_TYPE (op0), &vr0, &may_be_nonzero0,
 				  &must_be_nonzero0))
     return false;
-  if (!zero_nonzero_bits_from_vr (TREE_TYPE (op1), &vr1, &may_be_nonzero1,
+  if (!zero_nonzero_bits_from_vr (TREE_TYPE (op0), &vr1, &may_be_nonzero1,
 				  &must_be_nonzero1))
     return false;
+  if (TYPE_PRECISION (TREE_TYPE (op0)) != may_be_nonzero0.get_precision ())
+    {
+      may_be_nonzero0 = wide_int_to_tree (TREE_TYPE (op0), may_be_nonzero0);
+      must_be_nonzero0 = wide_int_to_tree (TREE_TYPE (op0), must_be_nonzero0);
+    }
+  if (TYPE_PRECISION (TREE_TYPE (op0)) != may_be_nonzero1.get_precision ())
+    {
+      may_be_nonzero1 = wide_int_to_tree (TREE_TYPE (op1), may_be_nonzero0);
+      must_be_nonzero1 = wide_int_to_tree (TREE_TYPE (op1), must_be_nonzero0);
+    }
 
   switch (gimple_assign_rhs_code (stmt))
     {
@@ -8752,9 +8882,9 @@ test_for_singularity (enum tree_code cond_code, tree op0,
   if (min && max)
     {
       if (compare_values (vr->min, min) == 1)
-	min = vr->min;
+	min = wide_int_to_tree (TREE_TYPE (op0), vr->min);
       if (compare_values (vr->max, max) == -1)
-	max = vr->max;
+	max = wide_int_to_tree (TREE_TYPE (op0), vr->max);
 
       /* If the new min/max values have converged to a single value,
 	 then there is only one value which can satisfy the condition,
@@ -9474,7 +9604,7 @@ simplify_stmt_for_jump_threading (gimple stmt, gimple within_stmt)
 	{
 	  extract_range_from_assignment (&new_vr, stmt);
 	  if (range_int_cst_singleton_p (&new_vr))
-	    return new_vr.min;
+	    return wide_int_to_tree (TREE_TYPE (lhs), new_vr.min);
 	}
     }
 

  reply	other threads:[~2014-09-04  3:41 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-27 10:01 Uros Bizjak
2014-08-27 10:07 ` Richard Biener
2014-08-27 10:32   ` Uros Bizjak
2014-08-27 10:32     ` Richard Biener
2014-09-01  8:48     ` Jakub Jelinek
2014-09-01  8:54       ` Uros Bizjak
2014-08-28  7:50   ` Kugan
2014-08-28  8:57     ` Richard Biener
2014-09-04  3:41       ` Kugan [this message]
2014-09-04 13:00         ` Richard Biener
2014-09-05  1:33           ` Kugan
2014-09-05  9:51             ` Richard Biener
2014-09-07  9:51               ` Kugan
2014-09-08  9:48                 ` Richard Biener
2014-09-09 10:06                   ` Kugan
2014-09-09 10:28                     ` Richard Biener
2014-11-09 23:30               ` [RFC] Elimination of zext/sext - type promotion pass Kugan
2014-11-10 12:56                 ` Richard Biener
2015-05-01  4:41                   ` Kugan
2015-05-08 12:48                     ` Richard Biener
2015-06-01 23:20                       ` Kugan
2015-06-19  2:55                         ` Kugan
2015-07-28 11:05                         ` Richard Biener
2015-08-05  0:12                           ` kugan
2015-08-05  9:10                             ` Richard Biener
2014-08-27 13:02 ` [PATCH 2/2] Enable elimination of zext/sext Kugan
2014-08-28  3:46   ` Kugan
2014-08-28  6:44     ` Marc Glisse
2014-08-28  7:29       ` Kugan
  -- strict thread matches above, loose matches on Subject: below --
2014-06-24 11:48 [PATCH 0/2] Zext/sext elimination using value range Kugan
2014-06-24 11:53 ` [PATCH 2/2] Enable elimination of zext/sext Kugan
2014-06-24 12:21   ` Jakub Jelinek
2014-06-25  8:15     ` Kugan
2014-06-25  8:36       ` Jakub Jelinek
2014-07-07  6:55         ` Kugan
2014-07-10 12:15           ` Richard Biener
2014-07-11 11:52             ` Kugan
2014-07-11 12:47               ` Richard Biener
2014-07-14  2:58                 ` Kugan
2014-07-14 20:11                   ` Bernhard Reutner-Fischer
2014-07-23 14:22                   ` Richard Biener
2014-08-01  4:51                     ` Kugan
2014-08-01 11:16                       ` Richard Biener
2014-08-01 16:04                         ` Kugan
2014-08-03 23:56                           ` Kugan
2014-08-05 14:18                           ` Richard Biener
2014-08-05 14:21                             ` Jakub Jelinek
2014-08-06 12:09                               ` Richard Biener
2014-08-06 13:22                                 ` Kugan
2014-08-06 13:29                                   ` Richard Biener
2014-08-07  5:25                                     ` Kugan
2014-08-07  8:09                                       ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5407DF57.2040902@linaro.org \
    --to=kugan.vivekanandarajah@linaro.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=richard.guenther@gmail.com \
    --cc=ubizjak@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).