Hi,

this is an ICE present on the mainline and 6 branch, a regression introduced 
by r241529 which added the consistency check for boolean values.  So it turns 
out that Ada is not the only producer of non-standard boolean types, there is 
even a helper function to do it in tree.c (build_nonstandard_boolean_type) and 
it builds even weirder boolean types than Ada since they are signed.

The problem is that -1 is not considered as a valid value for them any more 
and this confuses VRP.  Therefore the attached patch adjusts the consistency 
check to accept -1 instead of +1 for them.

Tested on x86_64-suse-linux, OK for the mainline and 6 branch?


2016-11-23  Eric Botcazou  <ebotca...@adacore.com>

        PR middle-end/78429
        * tree.h (wi::fits_to_boolean_p): New predicate.
        (wi::fits_to_tree_p): Use it for boolean types.
        * tree.c (int_fits_type_p): Likewise.


2016-11-23  Eric Botcazou  <ebotca...@adacore.com>

        * gcc.c-torture/compile/20161123-1.c: New test.

-- 
Eric Botcazou
/* PR middle-end/78429 */
/* Testcase by Chengnian Sun <chengnian...@gmail.com> */

int a[6];
char b;
unsigned c;
short d;
volatile int e;

int foo (void)
{
  int f;
  for (; c <= 2; c++) {
    d = 3;
    for (; d >= 0; d--) {
      int g = b;
      f = a[d] || b;
    }
    f || e;
  }
  return 0;
}
Index: tree.h
===================================================================
--- tree.h	(revision 242632)
+++ tree.h	(working copy)
@@ -5294,6 +5294,9 @@ wi::extended_tree <N>::get_len () const
 namespace wi
 {
   template <typename T>
+  bool fits_to_boolean_p (const T &x, const_tree);
+
+  template <typename T>
   bool fits_to_tree_p (const T &x, const_tree);
 
   wide_int min_value (const_tree);
@@ -5303,14 +5306,21 @@ namespace wi
 
 template <typename T>
 bool
+wi::fits_to_boolean_p (const T &x, const_tree type)
+{
+  return eq_p (x, 0) || eq_p (x, TYPE_UNSIGNED (type) ? 1 : -1);
+}
+
+template <typename T>
+bool
 wi::fits_to_tree_p (const T &x, const_tree type)
 {
-  /* Short-circuit boolean types since various transformations assume that
-     they can only take values 0 and 1.  */
+  /* Non-standard boolean types can have arbitrary precision but various
+     transformations assume that they can only take values 0 and +/-1.  */
   if (TREE_CODE (type) == BOOLEAN_TYPE)
-    return eq_p (x, 0) || eq_p (x, 1);
+    return fits_to_boolean_p (x, type);
 
-  if (TYPE_SIGN (type) == UNSIGNED)
+  if (TYPE_UNSIGNED (type))
     return eq_p (x, zext (x, TYPE_PRECISION (type)));
   else
     return eq_p (x, sext (x, TYPE_PRECISION (type)));
Index: tree.c
===================================================================
--- tree.c	(revision 242632)
+++ tree.c	(working copy)
@@ -9092,10 +9092,10 @@ int_fits_type_p (const_tree c, const_tre
   bool ok_for_low_bound, ok_for_high_bound;
   signop sgn_c = TYPE_SIGN (TREE_TYPE (c));
 
-  /* Short-circuit boolean types since various transformations assume that
-     they can only take values 0 and 1.  */
+  /* Non-standard boolean types can have arbitrary precision but various
+     transformations assume that they can only take values 0 and +/-1.  */
   if (TREE_CODE (type) == BOOLEAN_TYPE)
-    return integer_zerop (c) || integer_onep (c);
+    return wi::fits_to_boolean_p (c, type);
 
 retry:
   type_low_bound = TYPE_MIN_VALUE (type);

Reply via email to