public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 2/4 v3][PR 67328] Analyze some bit tests in VRP
@ 2017-05-29  6:59 Yuri Gribov
  2017-05-31 11:19 ` Richard Biener
  0 siblings, 1 reply; 2+ messages in thread
From: Yuri Gribov @ 2017-05-29  6:59 UTC (permalink / raw)
  To: GCC Patches; +Cc: Alan Modra, rguenth

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

This improve VRP handling for bitfield comparisons added by previous patch.

-I

[-- Attachment #2: 0002-Analyze-some-bit-tests-in-VRP.patch --]
[-- Type: application/octet-stream, Size: 3669 bytes --]

From f11d81a5f6cf1309e65c284072f5d5a164442082 Mon Sep 17 00:00:00 2001
From: Yury Gribov <tetra2005@gmail.com>
Date: Fri, 26 May 2017 07:56:47 +0100
Subject: [PATCH 2/4] Analyze some bit tests in VRP.

gcc/
2017-05-26  Yury Gribov  <tetra2005@gmail.com>

	* tree-vrp.c (is_masked_range_test): New function.
	(register_edge_assert_for): Determine ranges for
	some bit tests.
---
 gcc/tree-vrp.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)

diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 716a7c2..71d23fb 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -5628,6 +5628,84 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
     }
 }
 
+/* Check if comparison
+     NAME COND_OP INTEGER_CST
+   has a form of
+     (X & 11...100..0) COND_OP XX...X00...0
+   Such comparison can yield assertions like
+     X >= XX...X00...0
+     X <= XX...X11...1
+   in case of COND_OP being NE_EXPR or
+     X < XX...X00...0
+     X > XX...X11...1
+   in case of EQ_EXPR.  */
+
+static bool
+is_masked_range_test (tree name, tree valt, enum tree_code cond_code, bool is_else_edge,
+		      tree *new_name,
+		      tree *low, enum tree_code *low_code,
+		      tree *high, enum tree_code *high_code)
+{
+  gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+
+  if (!is_gimple_assign (def_stmt)
+      || gimple_assign_rhs_code (def_stmt) != BIT_AND_EXPR)
+    return false;
+
+  tree maskt = gimple_assign_rhs2 (def_stmt);
+  if (TREE_CODE (maskt) != INTEGER_CST)
+    return false;
+
+  wide_int mask = maskt,
+    inv_mask = ~mask,
+    val = valt;  // Assume VALT is INTEGER_CST
+
+  if ((inv_mask & (inv_mask + 1)) != 0
+      || (val & mask) != val)
+    return false;
+
+  tree t = gimple_assign_rhs1 (def_stmt);
+  tree type = TREE_TYPE (t);
+
+//  bool is_range = (cond_code == EQ_EXPR) ^ is_else_edge;
+  bool is_range = cond_code == EQ_EXPR;
+
+  wide_int min = wi::min_value (type),
+    max = wi::max_value (type);
+
+  if (is_range)
+    {
+      *low_code = val == min ? (enum tree_code) 0 : GE_EXPR;
+      *high_code = val == max ? (enum tree_code) 0 : LE_EXPR;
+    }
+  else
+    {
+      /* We can still generate assertion if one of alternatives
+	 is known to always be false.  */
+      if (val == min)
+	{
+	  *low_code = (enum tree_code) 0;
+	  *high_code = GT_EXPR;
+	}
+      else if ((val | inv_mask) == max)
+	{
+	  *low_code = LT_EXPR;
+	  *high_code = (enum tree_code) 0;
+	}
+      else
+	return false;
+    }
+
+  *new_name = t;
+  *low = wide_int_to_tree (type, val);
+  *high = wide_int_to_tree (type, val | inv_mask);
+
+  if (wi::neg_p (val, TYPE_SIGN (type)))
+    std::swap (*low, *high);
+
+  return true;
+}
+
 /* Try to register an edge assertion for SSA name NAME on edge E for
    the condition COND contributing to the conditional jump pointed to by
    SI.  */
@@ -5700,6 +5778,23 @@ register_edge_assert_for (tree name, edge e,
 	  register_edge_assert_for_1 (op1, EQ_EXPR, e, asserts);
 	}
     }
+
+  /* Sometimes we can infer ranges from (NAME & MASK) == VALUE.  */
+  if ((comp_code == EQ_EXPR || comp_code == NE_EXPR)
+      && TREE_CODE (val) == INTEGER_CST)
+    {
+      enum tree_code low_code, high_code;
+      tree low, high;
+      if (is_masked_range_test (name, val, comp_code, is_else_edge, &name, &low, &low_code, &high, &high_code))
+	{
+	  if (low_code)
+	    register_edge_assert_for_2 (name, e, low_code, name,
+					low, /*invert*/false, asserts);
+	  if (high_code)
+	    register_edge_assert_for_2 (name, e, high_code, name,
+					high, /*invert*/false, asserts);
+	}
+    }
 }
 
 /* Finish found ASSERTS for E and register them at GSI.  */
-- 
2.7.4


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH 2/4 v3][PR 67328] Analyze some bit tests in VRP
  2017-05-29  6:59 [PATCH 2/4 v3][PR 67328] Analyze some bit tests in VRP Yuri Gribov
@ 2017-05-31 11:19 ` Richard Biener
  0 siblings, 0 replies; 2+ messages in thread
From: Richard Biener @ 2017-05-31 11:19 UTC (permalink / raw)
  To: Yuri Gribov; +Cc: GCC Patches, Alan Modra, rguenth

On Mon, 29 May 2017, Yuri Gribov wrote:

> This improve VRP handling for bitfield comparisons added by previous patch.
> 
> -I

+is_masked_range_test (tree name, tree valt, enum tree_code cond_code, 
bool is_else_edge,
+                     tree *new_name,

long line

+  wide_int mask = maskt,
+    inv_mask = ~mask,
+    val = valt;  // Assume VALT is INTEGER_CST

indent is off here, please use separate declarations:

  wide_int mask = maskt;
  wide_int inv_mask = ~mask;
...

+//  bool is_range = (cond_code == EQ_EXPR) ^ is_else_edge;
+  bool is_range = cond_code == EQ_EXPR;
+

do not leave dead code around.

+  if (is_range)
+    {
+      *low_code = val == min ? (enum tree_code) 0 : GE_EXPR;
+      *high_code = val == max ? (enum tree_code) 0 : LE_EXPR;
+    }

please use ERROR_MARK here instead of (enum tree_code) 0.

+       {
+         if (low_code)

and check with != ERROR_MARK here.

+      if (is_masked_range_test (name, val, comp_code, is_else_edge, 
&name, &low, &low_code, &high, &high_code))
+       {

long line again.

Otherwise looks ok.

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-05-31 11:13 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-29  6:59 [PATCH 2/4 v3][PR 67328] Analyze some bit tests in VRP Yuri Gribov
2017-05-31 11:19 ` Richard Biener

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).