diff mbox

[gimplifier] : Make sure TRUTH_NOT_EXPR has boolean_type_node type and argument

Message ID BANLkTikQYQ+j-S8dkzvKWPjdkiXJJUx9Og@mail.gmail.com
State New
Headers show

Commit Message

Kai Tietz May 18, 2011, 6:52 a.m. UTC
2011/5/16 Richard Guenther <richard.guenther@gmail.com>:
> On Mon, May 16, 2011 at 3:45 PM, Michael Matz <matz@suse.de> wrote:
>> Hi,
>>
>> On Mon, 16 May 2011, Richard Guenther wrote:
>>
>>> > I think conversion _to_ BOOLEAN_TYPE shouldn't be useless, on the
>>> > grounds that it requires booleanization (at least conceptually), i.e.
>>> > conversion to a set of two values (no matter the precision or size)
>>> > based on the outcome of comparing the RHS value with
>>> > false_pre_image(TREE_TYPE(RHS)).
>>> >
>>> > Conversion _from_ BOOLEAN_TYPE can be regarded as useless, as the
>>> > conversions from false or true into false_pre_image or true_pre_image
>>> > always is simply an embedding of 0 or 1/-1 (depending on target type
>>> > signedness).  And if the BOOLEAN_TYPE and the LHS have same signedness
>>> > the bit representation of boolean_true_type is (or should be) the same
>>> > as the one converted to LHS (namely either 1 or -1).
>>>
>>> Sure, that would probably be enough to prevent non-BOOLEAN_TYPEs be used
>>> where BOOLEAN_TYPE nodes were used before.  It still will cause an
>>> artificial conversion from a single-bit bitfield read to a bool.
>>
>> Not if you're special casing single-bit conversions (on the grounds that a
>> booleanization from two-valued set to a different two-valued set of
>> the same signedness will not actually require a comparison).  I think it's
>> better to be very precise in our base predicates than to add various hacks
>> over the place to care for imprecision.
>
> Or require a 1-bit integral type for TRUTH_* operands only (which ensures
> the two-valueness which is what we really want).  That can be done
> by either fixing the frontends to make boolean_type_node have 1-bit
> precision or to build a middle-end private type with that constraints
> (though that's the more difficult route as we still do not have a strong
> FE - middle-end hand-off point, and it certainly is not the gimplifier).
>
> Long term all the global trees should be FE private and the middle-end
> should have its own set.
>
> Richard.
>
>>
>> Ciao,
>> Michael.
>

Hello,

initial idea was to check for logical operations that the conversion
to boolean_type_node
is useless.  This assumption was flawed by the fact that
boolean_type_node gets re-defined
in free_lang_decl to a 1-bit precision BOOL_TYPE_SIZE-ed type, if FE's
boolean_type_node
is incompatible to this.  By this FE's boolean_type_node gets via the
back-door incompatible
in tree-cfg checks.
So for all languages - but ADA - logical types have precision set to
one. Just for ADA case,
which requires a different boolean_type_node kind, we need to inspect
the inner type to be
a boolean.  As Fortran has also integer typed boolean compatible
types, we can't simply check
for BOOLEAN_TYPE here and need to check for precision first.

ChangeLog

2011-05-18  Kai Tietz

	PR middle-end/48989
	* tree-cfg.c (verify_gimple_assign_binary): Check lhs type
	for being compatible to boolean for logical operations.
	(verify_gimple_assign_unary): Likewise.
	(compatible_boolean_type_p): New helper.

Bootstrapped on x86_64-pc-linux-gnu. And regression tested for ADA
and Fortran.

Ok for apply?

Regards,
Kai
diff mbox

Patch

Index: gcc/gcc/tree-cfg.c
===================================================================
--- gcc.orig/gcc/tree-cfg.c	2011-05-16 14:26:12.369031500 +0200
+++ gcc/gcc/tree-cfg.c	2011-05-18 08:20:34.935819100 +0200
@@ -3220,6 +3220,31 @@  verify_gimple_comparison (tree type, tre
   return false;
 }
 
+/* Checks TYPE for being compatible to boolean. Returns
+   FALSE, if type is not compatible, otherwise TRUE.
+
+   A type is compatible if
+   a) TYPE_PRECISION is one.
+   b) The type - or the inner type - is of kind BOOLEAN_TYPE.  */
+
+static bool
+compatible_boolean_type_p (tree type)
+{
+  if (!type)
+    return false;
+  if (TYPE_PRECISION (type) == 1)
+    return true;
+
+  /* We try to look here into inner type, as ADA uses
+     boolean_type_node with type precision != 1.  */
+  while (TREE_TYPE (type)
+	 && (TREE_CODE (type) == INTEGER_TYPE
+	     || TREE_CODE (type) == REAL_TYPE))
+    type = TREE_TYPE (type);
+
+  return TYPE_PRECISION (type) == 1 || TREE_CODE (type) == BOOLEAN_TYPE;
+}
+
 /* Verify a gimple assignment statement STMT with an unary rhs.
    Returns true if anything is wrong.  */
 
@@ -3350,15 +3375,16 @@  verify_gimple_assign_unary (gimple stmt)
       return false;
 
     case TRUTH_NOT_EXPR:
-      if (!useless_type_conversion_p (boolean_type_node,  rhs1_type))
+
+      if (!useless_type_conversion_p (lhs_type,  rhs1_type)
+          || !compatible_boolean_type_p (lhs_type))
         {
-	    error ("invalid types in truth not");
-	    debug_generic_expr (lhs_type);
-	    debug_generic_expr (rhs1_type);
-	    return true;
+           error ("invalid types in truth not");
+           debug_generic_expr (lhs_type);
+           debug_generic_expr (rhs1_type);
+           return true;
         }
       break;
-
     case NEGATE_EXPR:
     case ABS_EXPR:
     case BIT_NOT_EXPR:
@@ -3558,10 +3584,11 @@  do_pointer_plus_expr_check:
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
       {
-	/* We allow only boolean typed or compatible argument and result.  */
-	if (!useless_type_conversion_p (boolean_type_node,  rhs1_type)
-	    || !useless_type_conversion_p (boolean_type_node,  rhs2_type)
-	    || !useless_type_conversion_p (boolean_type_node,  lhs_type))
+	/* We allow only boolean_typed or types with precision of one,
+	   or compatible argument and result.  */
+	if (!useless_type_conversion_p (lhs_type,  rhs1_type)
+	    || !useless_type_conversion_p (lhs_type,  rhs2_type)
+	    || !compatible_boolean_type_p (lhs_type))
 	  {
 	    error ("type mismatch in binary truth expression");
 	    debug_generic_expr (lhs_type);