From d38a878046aee24f3c0df7ccbd120f5d087000d4 Mon Sep 17 00:00:00 2001
From: Yury Gribov <tetra2005@gmail.com>
Date: Fri, 18 May 2018 14:05:16 +0200
Subject: [PATCH] 2018-05-20  Yury Gribov  <tetra2005@gmail.com>

	PR tree-optimization/85822

gcc/
	* tree-vrp.c (is_masked_range_test): Fix handling of negative
	constants.

gcc/testsuite/
	* c-c++-common/pr85822.c: New test.
---
 gcc/testsuite/c-c++-common/pr85822.c | 27 +++++++++++++++++++++++++++
 gcc/tree-vrp.c                       | 11 ++++++-----
 2 files changed, 33 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/pr85822.c

diff --git a/gcc/testsuite/c-c++-common/pr85822.c b/gcc/testsuite/c-c++-common/pr85822.c
new file mode 100644
index 0000000..3b09188
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr85822.c
@@ -0,0 +1,27 @@
+/* { dg-options "-O2" } */
+/* { dg-do run } */
+
+static const long long int TagTypeNumber = 0xffff000000000000ll;
+
+long long int x;
+
+void foo(void)
+{
+  x = TagTypeNumber + 1;
+}
+
+int main(int argc, char **argv)
+{
+  if (argc > 0)
+    foo ();
+
+  if ((x & TagTypeNumber) == TagTypeNumber)
+  {
+    unsigned y = (unsigned)x;
+    __builtin_printf ("v: %u\n", y);
+    if (y != 1)
+      __builtin_abort ();
+  }
+
+  return 0;
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index aa53db6..6c482dd 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3844,10 +3844,10 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
    Such comparison can yield assertions like
      X >= XX...X00...0
      X <= XX...X11...1
-   in case of COND_OP being NE_EXPR or
+   in case of COND_OP being EQ_EXPR or
      X < XX...X00...0
      X > XX...X11...1
-   in case of EQ_EXPR.  */
+   in case of NE_EXPR.  */
 
 static bool
 is_masked_range_test (tree name, tree valt, enum tree_code cond_code,
@@ -3867,6 +3867,10 @@ is_masked_range_test (tree name, tree valt, enum tree_code cond_code,
 
   wi::tree_to_wide_ref mask = wi::to_wide (maskt);
   wide_int inv_mask = ~mask;
+  /* Must have been removed by now so don't bother optimizing.  */
+  if (mask == 0 || inv_mask == 0)
+    return false;
+
   /* Assume VALT is INTEGER_CST.  */
   wi::tree_to_wide_ref val = wi::to_wide (valt);
 
@@ -3907,9 +3911,6 @@ is_masked_range_test (tree name, tree valt, enum tree_code cond_code,
   *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;
 }
 
-- 
2.9.4

