Patchwork [gimplifier] : Boolify more strict conditional expressions and transform simple form to binary

login
register
mail settings
Submitter Richard Guenther
Date May 11, 2011, 8:55 a.m.
Message ID <BANLkTin-=MKYvPgL8gZoDChkfxz94LUx_Q@mail.gmail.com>
Download mbox | patch
Permalink /patch/95193/
State New
Headers show

Comments

Richard Guenther - May 11, 2011, 8:55 a.m.
On Tue, May 10, 2011 at 9:26 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
> 2011/5/10 Kai Tietz <ktietz70@googlemail.com>:
>> 2011/5/10 Richard Guenther <richard.guenther@gmail.com>:
>>> On Tue, May 10, 2011 at 5:30 PM, Paolo Bonzini <bonzini@gnu.org> wrote:
>>>> On 05/10/2011 05:23 PM, Richard Guenther wrote:
>>>>>
>>>>> I suppose you have testcases for all the cases you looked at, please
>>>>> add some that cover these corner cases.
>>>>
>>>> Also, there is quite some tree-vrp.c dead code with these changes. Removing
>>>> the TRUTH_*_CODE handling in VRP will help finding more places where the
>>>> middle-end is building boolean operations.  There should be testcases
>>>> covering these parts of VRP.
>>>
>>> Btw, you can split the patch into two pieces - first, make TRUTH_*
>>> expressions correctly typed (take boolean typed operands and procude
>>> a boolean typed result) and verify that in verify_gimple_assign_binary.
>>> A second patch than can do the s/TRUTH_/BIT_/ substitution during
>>> gimplification.  That way the first (and more difficult) part doesn't get
>>> too big with unrelated changes.
>>>
>>> Richard.
>>>
>>>> Paolo
>>>>
>>>
>>
>> Well, I think I found one big issue here about booified expression of
>> condition. The gimple_boolify needs to handle COND_EXPR in more
>> detail. As if a conditional expression has to be boolified, it means
>> its condition and its other operands need to be boolified, too. And
>> this is for sure one cause, why I see for ANDIF/ORIF and the truth
>> AND|OR|XOR none boolean types.
>>
>> I will continue on that.
>>
>> To split this seems to make sense, as I have to touch much more areas
>> for the TRUTH to BIT conversion.
>>
>> Regards,
>> Kai
>>
>
> So I use this thread for first part of the series of patches. This one
> improves boolean type-logic
> during gimplification.
> To gimple_boolify the handling for COND_EXPR are added, and in general
> it is tried to do
> boolean operation just on boolean type.  As sadly fold-const (and here
> in special fold_truth_not_expr (), which doesn't provide by default
> boolean type and uses instead operand-type, which is IMHO a major flaw
> here.  But well, there are some comments indicating that this behavior
> is required due some other quirks. But this is for sure something to
> be cleaned up) produces truth operations with wrong type, which are in
> calculations not necessarily identifyable as truth ops anymore, this
> patch makes sure that for truth AND|OR|XOR original type remains.
>
> 2011-05-10  Kai Tietz
>
>        * gimplify.c (gimple_boolify): Handle COND_EXPR
>        and make sure that even if type is BOOLEAN for
>        TRUTH-opcodes the operands getting boolified.
>        (gimplify_expr): Boolify operand condition for
>        COND_EXPR.
>        Boolify truth opcodes AND, ANDIF, OR, ORIF, and XOR. Additional
>        take care that we keep expression's type.
>
> Ok for apply?

Posting patches inline makes it easier to put in review comments, so
please consider doing that.




Otherwise you wouldn't know whether your patch was complete (how
did you verify that?).

Richard.


> Regards,
> Kai
>
Kai Tietz - May 11, 2011, 9:10 a.m.
2011/5/11 Richard Guenther <richard.guenther@gmail.com>:
> On Tue, May 10, 2011 at 9:26 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
>> 2011/5/10 Kai Tietz <ktietz70@googlemail.com>:
>>> 2011/5/10 Richard Guenther <richard.guenther@gmail.com>:
>>>> On Tue, May 10, 2011 at 5:30 PM, Paolo Bonzini <bonzini@gnu.org> wrote:
>>>>> On 05/10/2011 05:23 PM, Richard Guenther wrote:
>>>>>>
>>>>>> I suppose you have testcases for all the cases you looked at, please
>>>>>> add some that cover these corner cases.
>>>>>
>>>>> Also, there is quite some tree-vrp.c dead code with these changes. Removing
>>>>> the TRUTH_*_CODE handling in VRP will help finding more places where the
>>>>> middle-end is building boolean operations.  There should be testcases
>>>>> covering these parts of VRP.
>>>>
>>>> Btw, you can split the patch into two pieces - first, make TRUTH_*
>>>> expressions correctly typed (take boolean typed operands and procude
>>>> a boolean typed result) and verify that in verify_gimple_assign_binary.
>>>> A second patch than can do the s/TRUTH_/BIT_/ substitution during
>>>> gimplification.  That way the first (and more difficult) part doesn't get
>>>> too big with unrelated changes.
>>>>
>>>> Richard.
>>>>
>>>>> Paolo
>>>>>
>>>>
>>>
>>> Well, I think I found one big issue here about booified expression of
>>> condition. The gimple_boolify needs to handle COND_EXPR in more
>>> detail. As if a conditional expression has to be boolified, it means
>>> its condition and its other operands need to be boolified, too. And
>>> this is for sure one cause, why I see for ANDIF/ORIF and the truth
>>> AND|OR|XOR none boolean types.
>>>
>>> I will continue on that.
>>>
>>> To split this seems to make sense, as I have to touch much more areas
>>> for the TRUTH to BIT conversion.
>>>
>>> Regards,
>>> Kai
>>>
>>
>> So I use this thread for first part of the series of patches. This one
>> improves boolean type-logic
>> during gimplification.
>> To gimple_boolify the handling for COND_EXPR are added, and in general
>> it is tried to do
>> boolean operation just on boolean type.  As sadly fold-const (and here
>> in special fold_truth_not_expr (), which doesn't provide by default
>> boolean type and uses instead operand-type, which is IMHO a major flaw
>> here.  But well, there are some comments indicating that this behavior
>> is required due some other quirks. But this is for sure something to
>> be cleaned up) produces truth operations with wrong type, which are in
>> calculations not necessarily identifyable as truth ops anymore, this
>> patch makes sure that for truth AND|OR|XOR original type remains.
>>
>> 2011-05-10  Kai Tietz
>>
>>        * gimplify.c (gimple_boolify): Handle COND_EXPR
>>        and make sure that even if type is BOOLEAN for
>>        TRUTH-opcodes the operands getting boolified.
>>        (gimplify_expr): Boolify operand condition for
>>        COND_EXPR.
>>        Boolify truth opcodes AND, ANDIF, OR, ORIF, and XOR. Additional
>>        take care that we keep expression's type.
>>
>> Ok for apply?
>
> Posting patches inline makes it easier to put in review comments, so
> please consider doing that.

Ok, I think about this. Not sure how well, google-mail handles this.
I'll try next time.

> Index: gcc/gcc/gimplify.c
> ===================================================================
> --- gcc.orig/gcc/gimplify.c     2011-05-10 18:31:40.000000000 +0200
> +++ gcc/gcc/gimplify.c  2011-05-10 21:14:49.106340400 +0200
> @@ -2824,11 +2824,20 @@ gimple_boolify (tree expr)
>        }
>     }
>
> -  if (TREE_CODE (type) == BOOLEAN_TYPE)
> -    return expr;
> -
>   switch (TREE_CODE (expr))
>     {
> +    case COND_EXPR:
> +      /* If we have a conditional expression, which shall be
> +         boolean, take care we boolify also their left and right arm.  */
> +      if (TREE_OPERAND (expr, 2) != NULL_TREE && !VOID_TYPE_P
> (TREE_TYPE (TREE_OPERAND (expr, 2))))
> +        TREE_OPERAND (expr, 2) = gimple_boolify (TREE_OPERAND (expr, 2));
> +      if (TREE_OPERAND (expr, 1) != NULL_TREE && !VOID_TYPE_P
> (TREE_TYPE (TREE_OPERAND (expr, 1))))
> +        TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
> +      TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
> +      if (TREE_CODE (type) == BOOLEAN_TYPE)
> +       return expr;
> +      return fold_convert_loc (loc, boolean_type_node, expr);
> +
>
> That looks like premature optimization.  Why isn't it enough to
> fold-convert the COND_EXPR itself?  Thus, I don't see why the
> existing gimple_boolify isn't enough.

See description of recent update patch.  It isn't enough.

>     case TRUTH_AND_EXPR:
>     case TRUTH_OR_EXPR:
>     case TRUTH_XOR_EXPR:
> @@ -2851,6 +2860,8 @@ gimple_boolify (tree expr)
>     default:
>       /* Other expressions that get here must have boolean values, but
>         might need to be converted to the appropriate mode.  */
> +      if (TREE_CODE (type) == BOOLEAN_TYPE)
> +       return expr;
>       return fold_convert_loc (loc, boolean_type_node, expr);
>     }
>  }
> @@ -6714,6 +6725,7 @@ gimplify_expr (tree *expr_p, gimple_seq
>          break;
>
>        case COND_EXPR:
> +         TREE_OPERAND (*expr_p, 0) = gimple_boolify (TREE_OPERAND (*expr_p, 0));
>          ret = gimplify_cond_expr (expr_p, pre_p, fallback);
>
> This boolification should be done by gimplify_cond_expr as I said
> in the previous review.  It does already handle this perfectly fine.

No, but this variant is a bit too weak (see again updated patch). As
the COND itself can be TRUTH operation, which otherwise will later on
introduces none-boolified inner ANDIF/ORIF/AND/OR/XOR truth
expressions.


>          /* C99 code may assign to an array in a structure value of a
> @@ -6762,6 +6774,17 @@ gimplify_expr (tree *expr_p, gimple_seq
>
>        case TRUTH_ANDIF_EXPR:
>        case TRUTH_ORIF_EXPR:
> +         /* This shouldn't happen, but due fold-const (and here especially
> +            fold_truth_not_expr) happily uses operand type and doesn't
> +            automatically uses boolean_type as result, this happens.  */
> +         if (TREE_CODE (TREE_TYPE (*expr_p)) != BOOLEAN_TYPE)
> +           {
> +             tree type = TREE_TYPE (*expr_p);
> +             *expr_p = fold_convert (type, gimple_boolify (*expr_p));
> +             ret = GS_OK;
> +             break;
> +           }
> +         *expr_p = gimple_boolify (*expr_p);
>
> This shouldn't be necessary at all.  Instead gimplify_boolean_expr
> should deal with it - which it magically does by building a COND_EXPR
> which should already deal with all cases just fine.
>
>          /* Pass the source location of the outer expression.  */
>          ret = gimplify_boolean_expr (expr_p, saved_location);
>          break;
> @@ -7203,6 +7226,17 @@ gimplify_expr (tree *expr_p, gimple_seq
>        case TRUTH_AND_EXPR:
>        case TRUTH_OR_EXPR:
>        case TRUTH_XOR_EXPR:
> +         /* This shouldn't happen, but due fold-const (and here especially
> +            fold_truth_not_expr) happily uses operand type and doesn't
> +            automatically uses boolean_type as result, this happens.  */
> +         if (TREE_CODE (TREE_TYPE (*expr_p)) != BOOLEAN_TYPE)
> +           {
> +             tree type = TREE_TYPE (*expr_p);
> +             *expr_p = fold_convert (type, gimple_boolify (*expr_p));
> +             ret = GS_OK;
> +             break;
> +           }
> +         *expr_p = gimple_boolify (*expr_p);
>
> Now this is the only place where we need to do something.  And it
> nearly looks ok but IMHO should simply do
>
>             tree orig_type = TREE_TYPE (*expr_p);
>             *expr_p = gimple_boolify (*expr_p);
>             if (TREE_CODE (orig_type) != BOOLEAN_TYPE)
>               {
>                 *expr_p = fold_convert (orig_type, *expr_p);
>                 ret = GS_OK;
>                 break;
>               }
>
>          /* Classified as tcc_expression.  */
>          goto expr_2;
>
> You lack a tree-cfg.c hunk to verify that the TRUTH_* exprs have
> correct types.  Sth like

Ok, I will add this.  With conditional expression checking, this
should be doable to check here for XOR/AND/OR truth.

> Index: gcc/tree-cfg.c
> ===================================================================
> --- gcc/tree-cfg.c      (revision 173611)
> +++ gcc/tree-cfg.c      (working copy)
> @@ -3542,9 +3615,9 @@ do_pointer_plus_expr_check:
>     case TRUTH_XOR_EXPR:
>       {
>        /* We allow any kind of integral typed argument and result.  */
> -       if (!INTEGRAL_TYPE_P (rhs1_type)
> -           || !INTEGRAL_TYPE_P (rhs2_type)
> -           || !INTEGRAL_TYPE_P (lhs_type))
> +       if (TREE_CODE (rhs1_type) != BOOLEAN_TYPE
> +           || TREE_CODE (rhs2_type) != BOOLEAN_TYPE
> +           || TREE_CODE (lhs_type) != BOOLEAN_TYPE)
>          {
>            error ("type mismatch in binary truth expression");
>            debug_generic_expr (lhs_type);
>
>
> Otherwise you wouldn't know whether your patch was complete (how
> did you verify that?).
>
> Richard.
>
>
>> Regards,
>> Kai
>>

Regards,
Kai
Kai Tietz - May 11, 2011, 10:01 a.m.
2011/5/11 Richard Guenther <richard.guenther@gmail.com>:
> On Tue, May 10, 2011 at 9:26 PM, Kai Tietz <ktietz70@googlemail.com> wrote:
>> 2011/5/10 Kai Tietz <ktietz70@googlemail.com>:
>>> 2011/5/10 Richard Guenther <richard.guenther@gmail.com>:
>>>> On Tue, May 10, 2011 at 5:30 PM, Paolo Bonzini <bonzini@gnu.org> wrote:
>>>>> On 05/10/2011 05:23 PM, Richard Guenther wrote:
>>>>>>
>>>>>> I suppose you have testcases for all the cases you looked at, please
>>>>>> add some that cover these corner cases.
>>>>>
>>>>> Also, there is quite some tree-vrp.c dead code with these changes. Removing
>>>>> the TRUTH_*_CODE handling in VRP will help finding more places where the
>>>>> middle-end is building boolean operations.  There should be testcases
>>>>> covering these parts of VRP.
>>>>
>>>> Btw, you can split the patch into two pieces - first, make TRUTH_*
>>>> expressions correctly typed (take boolean typed operands and procude
>>>> a boolean typed result) and verify that in verify_gimple_assign_binary.
>>>> A second patch than can do the s/TRUTH_/BIT_/ substitution during
>>>> gimplification.  That way the first (and more difficult) part doesn't get
>>>> too big with unrelated changes.
>>>>
>>>> Richard.
>>>>
>>>>> Paolo
>>>>>
>>>>
>>>
>>> Well, I think I found one big issue here about booified expression of
>>> condition. The gimple_boolify needs to handle COND_EXPR in more
>>> detail. As if a conditional expression has to be boolified, it means
>>> its condition and its other operands need to be boolified, too. And
>>> this is for sure one cause, why I see for ANDIF/ORIF and the truth
>>> AND|OR|XOR none boolean types.
>>>
>>> I will continue on that.
>>>
>>> To split this seems to make sense, as I have to touch much more areas
>>> for the TRUTH to BIT conversion.
>>>
>>> Regards,
>>> Kai
>>>
>>
>> So I use this thread for first part of the series of patches. This one
>> improves boolean type-logic
>> during gimplification.
>> To gimple_boolify the handling for COND_EXPR are added, and in general
>> it is tried to do
>> boolean operation just on boolean type.  As sadly fold-const (and here
>> in special fold_truth_not_expr (), which doesn't provide by default
>> boolean type and uses instead operand-type, which is IMHO a major flaw
>> here.  But well, there are some comments indicating that this behavior
>> is required due some other quirks. But this is for sure something to
>> be cleaned up) produces truth operations with wrong type, which are in
>> calculations not necessarily identifyable as truth ops anymore, this
>> patch makes sure that for truth AND|OR|XOR original type remains.
>>
>> 2011-05-10  Kai Tietz
>>
>>        * gimplify.c (gimple_boolify): Handle COND_EXPR
>>        and make sure that even if type is BOOLEAN for
>>        TRUTH-opcodes the operands getting boolified.
>>        (gimplify_expr): Boolify operand condition for
>>        COND_EXPR.
>>        Boolify truth opcodes AND, ANDIF, OR, ORIF, and XOR. Additional
>>        take care that we keep expression's type.
>>
>> Ok for apply?
>
> Posting patches inline makes it easier to put in review comments, so
> please consider doing that.
>
>
> Index: gcc/gcc/gimplify.c
> ===================================================================
> --- gcc.orig/gcc/gimplify.c     2011-05-10 18:31:40.000000000 +0200
> +++ gcc/gcc/gimplify.c  2011-05-10 21:14:49.106340400 +0200
> @@ -2824,11 +2824,20 @@ gimple_boolify (tree expr)
>        }
>     }
>
> -  if (TREE_CODE (type) == BOOLEAN_TYPE)
> -    return expr;
> -
>   switch (TREE_CODE (expr))
>     {
> +    case COND_EXPR:
> +      /* If we have a conditional expression, which shall be
> +         boolean, take care we boolify also their left and right arm.  */
> +      if (TREE_OPERAND (expr, 2) != NULL_TREE && !VOID_TYPE_P
> (TREE_TYPE (TREE_OPERAND (expr, 2))))
> +        TREE_OPERAND (expr, 2) = gimple_boolify (TREE_OPERAND (expr, 2));
> +      if (TREE_OPERAND (expr, 1) != NULL_TREE && !VOID_TYPE_P
> (TREE_TYPE (TREE_OPERAND (expr, 1))))
> +        TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
> +      TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
> +      if (TREE_CODE (type) == BOOLEAN_TYPE)
> +       return expr;
> +      return fold_convert_loc (loc, boolean_type_node, expr);
> +
>
> That looks like premature optimization.  Why isn't it enough to
> fold-convert the COND_EXPR itself?  Thus, I don't see why the
> existing gimple_boolify isn't enough.

Old code simple casted condition expression to boolean type, but
didn't converted inner arms.  By this the arms are remaining by their
old type, which later then gets converted. This is for a condition of
kind COND_EXPR pretty bad, as exactly this leads us to useless type
conversion in inner arms.

>     case TRUTH_AND_EXPR:
>     case TRUTH_OR_EXPR:
>     case TRUTH_XOR_EXPR:
> @@ -2851,6 +2860,8 @@ gimple_boolify (tree expr)
>     default:
>       /* Other expressions that get here must have boolean values, but
>         might need to be converted to the appropriate mode.  */
> +      if (TREE_CODE (type) == BOOLEAN_TYPE)
> +       return expr;
>       return fold_convert_loc (loc, boolean_type_node, expr);
>     }
>  }
> @@ -6714,6 +6725,7 @@ gimplify_expr (tree *expr_p, gimple_seq
>          break;
>
>        case COND_EXPR:
> +         TREE_OPERAND (*expr_p, 0) = gimple_boolify (TREE_OPERAND (*expr_p, 0));
>          ret = gimplify_cond_expr (expr_p, pre_p, fallback);
>
> This boolification should be done by gimplify_cond_expr as I said
> in the previous review.  It does already handle this perfectly fine.
>
>          /* C99 code may assign to an array in a structure value of a
> @@ -6762,6 +6774,17 @@ gimplify_expr (tree *expr_p, gimple_seq
>
>        case TRUTH_ANDIF_EXPR:
>        case TRUTH_ORIF_EXPR:
> +         /* This shouldn't happen, but due fold-const (and here especially
> +            fold_truth_not_expr) happily uses operand type and doesn't
> +            automatically uses boolean_type as result, this happens.  */
> +         if (TREE_CODE (TREE_TYPE (*expr_p)) != BOOLEAN_TYPE)
> +           {
> +             tree type = TREE_TYPE (*expr_p);
> +             *expr_p = fold_convert (type, gimple_boolify (*expr_p));
> +             ret = GS_OK;
> +             break;
> +           }
> +         *expr_p = gimple_boolify (*expr_p);
>
> This shouldn't be necessary at all.  Instead gimplify_boolean_expr
> should deal with it - which it magically does by building a COND_EXPR
> which should already deal with all cases just fine.

No, see above the comment about COND_EXPR in gimple_boolify. This can
happen in cases an ANDIF/ORIF expression (which later gets and AND/OR)
would be on an arm of a COND_EXPR, which simply gets converted to
boolean by casting.

>          /* Pass the source location of the outer expression.  */
>          ret = gimplify_boolean_expr (expr_p, saved_location);
>          break;
> @@ -7203,6 +7226,17 @@ gimplify_expr (tree *expr_p, gimple_seq
>        case TRUTH_AND_EXPR:
>        case TRUTH_OR_EXPR:
>        case TRUTH_XOR_EXPR:
> +         /* This shouldn't happen, but due fold-const (and here especially
> +            fold_truth_not_expr) happily uses operand type and doesn't
> +            automatically uses boolean_type as result, this happens.  */
> +         if (TREE_CODE (TREE_TYPE (*expr_p)) != BOOLEAN_TYPE)
> +           {
> +             tree type = TREE_TYPE (*expr_p);
> +             *expr_p = fold_convert (type, gimple_boolify (*expr_p));
> +             ret = GS_OK;
> +             break;
> +           }
> +         *expr_p = gimple_boolify (*expr_p);

Regards,
Kai

Patch

Index: gcc/gcc/gimplify.c
===================================================================
--- gcc.orig/gcc/gimplify.c	2011-05-10 18:31:40.000000000 +0200
+++ gcc/gcc/gimplify.c	2011-05-10 21:14:49.106340400 +0200
@@ -2824,11 +2824,20 @@  gimple_boolify (tree expr)
 	}
     }

-  if (TREE_CODE (type) == BOOLEAN_TYPE)
-    return expr;
-
   switch (TREE_CODE (expr))
     {
+    case COND_EXPR:
+      /* If we have a conditional expression, which shall be
+         boolean, take care we boolify also their left and right arm.  */
+      if (TREE_OPERAND (expr, 2) != NULL_TREE && !VOID_TYPE_P
(TREE_TYPE (TREE_OPERAND (expr, 2))))
+        TREE_OPERAND (expr, 2) = gimple_boolify (TREE_OPERAND (expr, 2));
+      if (TREE_OPERAND (expr, 1) != NULL_TREE && !VOID_TYPE_P
(TREE_TYPE (TREE_OPERAND (expr, 1))))
+        TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
+      TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
+      if (TREE_CODE (type) == BOOLEAN_TYPE)
+	return expr;
+      return fold_convert_loc (loc, boolean_type_node, expr);
+

That looks like premature optimization.  Why isn't it enough to
fold-convert the COND_EXPR itself?  Thus, I don't see why the
existing gimple_boolify isn't enough.

     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
@@ -2851,6 +2860,8 @@  gimple_boolify (tree expr)
     default:
       /* Other expressions that get here must have boolean values, but
 	 might need to be converted to the appropriate mode.  */
+      if (TREE_CODE (type) == BOOLEAN_TYPE)
+	return expr;
       return fold_convert_loc (loc, boolean_type_node, expr);
     }
 }
@@ -6714,6 +6725,7 @@  gimplify_expr (tree *expr_p, gimple_seq
 	  break;

 	case COND_EXPR:
+	  TREE_OPERAND (*expr_p, 0) = gimple_boolify (TREE_OPERAND (*expr_p, 0));
 	  ret = gimplify_cond_expr (expr_p, pre_p, fallback);

This boolification should be done by gimplify_cond_expr as I said
in the previous review.  It does already handle this perfectly fine.

 	  /* C99 code may assign to an array in a structure value of a
@@ -6762,6 +6774,17 @@  gimplify_expr (tree *expr_p, gimple_seq

 	case TRUTH_ANDIF_EXPR:
 	case TRUTH_ORIF_EXPR:
+	  /* This shouldn't happen, but due fold-const (and here especially
+	     fold_truth_not_expr) happily uses operand type and doesn't
+	     automatically uses boolean_type as result, this happens.  */
+	  if (TREE_CODE (TREE_TYPE (*expr_p)) != BOOLEAN_TYPE)
+	    {
+	      tree type = TREE_TYPE (*expr_p);
+	      *expr_p = fold_convert (type, gimple_boolify (*expr_p));
+	      ret = GS_OK;
+	      break;
+	    }
+	  *expr_p = gimple_boolify (*expr_p);

This shouldn't be necessary at all.  Instead gimplify_boolean_expr
should deal with it - which it magically does by building a COND_EXPR
which should already deal with all cases just fine.

 	  /* Pass the source location of the outer expression.  */
 	  ret = gimplify_boolean_expr (expr_p, saved_location);
 	  break;
@@ -7203,6 +7226,17 @@  gimplify_expr (tree *expr_p, gimple_seq
 	case TRUTH_AND_EXPR:
 	case TRUTH_OR_EXPR:
 	case TRUTH_XOR_EXPR:
+	  /* This shouldn't happen, but due fold-const (and here especially
+	     fold_truth_not_expr) happily uses operand type and doesn't
+	     automatically uses boolean_type as result, this happens.  */
+	  if (TREE_CODE (TREE_TYPE (*expr_p)) != BOOLEAN_TYPE)
+	    {
+	      tree type = TREE_TYPE (*expr_p);
+	      *expr_p = fold_convert (type, gimple_boolify (*expr_p));
+	      ret = GS_OK;
+	      break;
+	    }
+	  *expr_p = gimple_boolify (*expr_p);

Now this is the only place where we need to do something.  And it
nearly looks ok but IMHO should simply do

             tree orig_type = TREE_TYPE (*expr_p);
             *expr_p = gimple_boolify (*expr_p);
             if (TREE_CODE (orig_type) != BOOLEAN_TYPE)
               {
                 *expr_p = fold_convert (orig_type, *expr_p);
                 ret = GS_OK;
                 break;
               }

 	  /* Classified as tcc_expression.  */
 	  goto expr_2;

You lack a tree-cfg.c hunk to verify that the TRUTH_* exprs have
correct types.  Sth like

Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c      (revision 173611)
+++ gcc/tree-cfg.c      (working copy)
@@ -3542,9 +3615,9 @@  do_pointer_plus_expr_check:
     case TRUTH_XOR_EXPR:
       {
        /* We allow any kind of integral typed argument and result.  */
-       if (!INTEGRAL_TYPE_P (rhs1_type)
-           || !INTEGRAL_TYPE_P (rhs2_type)
-           || !INTEGRAL_TYPE_P (lhs_type))
+       if (TREE_CODE (rhs1_type) != BOOLEAN_TYPE
+           || TREE_CODE (rhs2_type) != BOOLEAN_TYPE
+           || TREE_CODE (lhs_type) != BOOLEAN_TYPE)
          {
            error ("type mismatch in binary truth expression");
            debug_generic_expr (lhs_type);