Re: [patch tree-optimization]: [1 of 3]: Boolify compares & more

2011-07-08 Thread Kai Tietz
2011/7/8 Richard Guenther :
> On Fri, Jul 8, 2011 at 11:28 AM, Kai Tietz  wrote
>> 2011/7/8 Richard Guenther :
>>> On Thu, Jul 7, 2011 at 6:06 PM, Kai Tietz  wrote:
 Hello,

 This patch - first of series - adds to fold and some helper routines 
 support
 for one-bit precision bitwise folding and detection.
 This patch is necessary for - next patch of series - boolification of
 comparisons.

 Bootstrapped and regression tested for all standard-languages (plus
 Ada and Obj-C++) on host x86_64-pc-linux-gnu.

 Ok for apply?
>>>
>>> Factoring out fold_truth_andor to a function should be done separately.
>>> A patch that does just that is pre-approved.
>>
>> Ok I will sent for this a separate patch. But in fact it makes just
>> sense together with the 1-bit precision bitwise support, too.
>
> No, it makes sense anyway to get rid of that goto.  Note _only_ factoring
> out the function, not changing anything in it.

Done.

>>> Otherwise the patch globs too many changes and lacks reasoning.
>>> Why do we want to handle all this in fold when the boolification
>>> happens only after gimplification?
>>
>> We still rely on truth/bitwise folding on fold-const.  Also we need to
>> handle this for passes, which are using fold_binary to optimize  and
>> handle boolified operations - like tree-ssa-reassoc, of tree-vect*.
>> This support in fold-const is necessary when we are preserving casts
>> from/to boolean, as otherwise we don't fold bitwise-binary with
>> compares proper anymore.  Additionally we have to take care that we
>> don't enter TRUTH_(AND|OR|XOR) expressions on boolified trees, as
>> otherwise tree-cfg will barf. Also we need to take care that types of
>> comparisons and TRUTH_NOT expressions are boolean one, as otherwise
>> again tree-cfg will detect incompatible types for those expressions.
>
> Sounds like many different things for many individual patches.  Btw,
> I'd rather have the tree passes that rely on fold call a gimple specific
> wrapper where we can add such things (and also use gimple/SSA
> specific optimizations, like less strict typing), like
> gimple_fold_binary (), see also my gimple folding proposal from
> earlier this year. http://gcc.gnu.org/ml/gcc-patches/2011-03/msg01099.html

Well, this is for sure a good thing, but didn't solve the issues about
fold-const and 1-bit precision bitwise-operations. We need to handle
them in fold-const as otherwise even worse things are happening there.
 As fold-const happily decides that bitwise-binaries with comparisons
or thruth valued arguments getting transformed back into
TRUTH_(AND|OR|XOR)[IF]_EXPRs, which is indeed contra-productive on an
already gimplified tree.
For sure it would be better to avoid for such passes fold-const at all
and have instead a pure-ssa-named folding mechanism, but this is a
different story and not part of this patch.  Focus here is that we are
again able to do proper folding on boolified bitwise operations and to
provide to some passes the knowledge that a 1-bit precision bitwise
operation is an equivalent to a TRUTH_(AND|OR|XOR) and can be handled.

Regards,
Kai


Re: [patch tree-optimization]: [1 of 3]: Boolify compares & more

2011-07-08 Thread Richard Guenther
On Fri, Jul 8, 2011 at 11:28 AM, Kai Tietz  wrote
> 2011/7/8 Richard Guenther :
>> On Thu, Jul 7, 2011 at 6:06 PM, Kai Tietz  wrote:
>>> Hello,
>>>
>>> This patch - first of series - adds to fold and some helper routines support
>>> for one-bit precision bitwise folding and detection.
>>> This patch is necessary for - next patch of series - boolification of
>>> comparisons.
>>>
>>> Bootstrapped and regression tested for all standard-languages (plus
>>> Ada and Obj-C++) on host x86_64-pc-linux-gnu.
>>>
>>> Ok for apply?
>>
>> Factoring out fold_truth_andor to a function should be done separately.
>> A patch that does just that is pre-approved.
>
> Ok I will sent for this a separate patch. But in fact it makes just
> sense together with the 1-bit precision bitwise support, too.

No, it makes sense anyway to get rid of that goto.  Note _only_ factoring
out the function, not changing anything in it.

>> Otherwise the patch globs too many changes and lacks reasoning.
>> Why do we want to handle all this in fold when the boolification
>> happens only after gimplification?
>
> We still rely on truth/bitwise folding on fold-const.  Also we need to
> handle this for passes, which are using fold_binary to optimize  and
> handle boolified operations - like tree-ssa-reassoc, of tree-vect*.
> This support in fold-const is necessary when we are preserving casts
> from/to boolean, as otherwise we don't fold bitwise-binary with
> compares proper anymore.  Additionally we have to take care that we
> don't enter TRUTH_(AND|OR|XOR) expressions on boolified trees, as
> otherwise tree-cfg will barf. Also we need to take care that types of
> comparisons and TRUTH_NOT expressions are boolean one, as otherwise
> again tree-cfg will detect incompatible types for those expressions.

Sounds like many different things for many individual patches.  Btw,
I'd rather have the tree passes that rely on fold call a gimple specific
wrapper where we can add such things (and also use gimple/SSA
specific optimizations, like less strict typing), like
gimple_fold_binary (), see also my gimple folding proposal from
earlier this year. http://gcc.gnu.org/ml/gcc-patches/2011-03/msg01099.html

Richard.

>> Thanks,
>> Richard.
>>
>>> Regards,
>>> Kai
>>>
>>> ChangeLog
>>>
>>> 2011-07-07  Kai Tietz  
>>>
>>>        * fold-const.c (fold_truth_not_expr): Handle
>>>        one bit precision bitwise operations.
>>>        (fold_range_test): Likewise.
>>>        (fold_truthop): Likewise.
>>>        (fold_binary_loc): Likewise.
>>>        (fold_truth_andor): Function replaces truth_andor
>>>        label.
>>>        (fold_ternary_loc): Use truth_value_type_p instead
>>>        of truth_value_p.
>>>        * gimple.c (canonicalize_cond_expr_cond): Likewise.
>>>        * gimplify.c (gimple_boolify): Likewise.
>>>        * tree-ssa-structalias.c (find_func_aliases): Likewise.
>>>        * tree-ssa-forwprop.c (truth_valued_ssa_name): Likewise.
>>>        * tree.h (truth_value_type_p): New function.
>>>        (truth_value_p): Implemented as macro via truth_value_type_p.
>>>
>>>
>>> Index: gcc-head/gcc/fold-const.c
>>> ===
>>> --- gcc-head.orig/gcc/fold-const.c
>>> +++ gcc-head/gcc/fold-const.c
>>> @@ -3074,20 +3074,35 @@ fold_truth_not_expr (location_t loc, tre
>>>     case INTEGER_CST:
>>>       return constant_boolean_node (integer_zerop (arg), type);
>>>
>>> +    case BIT_AND_EXPR:
>>> +      if (integer_onep (TREE_OPERAND (arg, 1)))
>>> +       return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 
>>> 0));
>>> +      if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
>>> +        return NULL_TREE;
>>> +      /* fall through */
>>>     case TRUTH_AND_EXPR:
>>>       loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
>>>       loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
>>> -      return build2_loc (loc, TRUTH_OR_EXPR, type,
>>> +      return build2_loc (loc, (code == BIT_AND_EXPR ? BIT_IOR_EXPR
>>> +                                                   : TRUTH_OR_EXPR), type,
>>>                         invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
>>>                         invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 
>>> 1)));
>>>
>>> +    case BIT_IOR_EXPR:
>>> +      if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
>>> +        return NULL_TREE;
>>> +      /* fall through.  */
>>>     case TRUTH_OR_EXPR:
>>>       loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
>>>       loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
>>> -      return build2_loc (loc, TRUTH_AND_EXPR, type,
>>> +      return build2_loc (loc, (code == BIT_IOR_EXPR ? BIT_AND_EXPR
>>> +                                                   : TRUTH_AND_EXPR), type,
>>>                         invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
>>>                         invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 
>>> 1)));
>>> -
>>> +    case BIT_XOR_EXPR:

Re: [patch tree-optimization]: [1 of 3]: Boolify compares & more

2011-07-08 Thread Kai Tietz
2011/7/8 Richard Guenther :
> On Thu, Jul 7, 2011 at 6:06 PM, Kai Tietz  wrote:
>> Hello,
>>
>> This patch - first of series - adds to fold and some helper routines support
>> for one-bit precision bitwise folding and detection.
>> This patch is necessary for - next patch of series - boolification of
>> comparisons.
>>
>> Bootstrapped and regression tested for all standard-languages (plus
>> Ada and Obj-C++) on host x86_64-pc-linux-gnu.
>>
>> Ok for apply?
>
> Factoring out fold_truth_andor to a function should be done separately.
> A patch that does just that is pre-approved.

Ok I will sent for this a separate patch. But in fact it makes just
sense together with the 1-bit precision bitwise support, too.

> Otherwise the patch globs too many changes and lacks reasoning.
> Why do we want to handle all this in fold when the boolification
> happens only after gimplification?

We still rely on truth/bitwise folding on fold-const.  Also we need to
handle this for passes, which are using fold_binary to optimize  and
handle boolified operations - like tree-ssa-reassoc, of tree-vect*.
This support in fold-const is necessary when we are preserving casts
from/to boolean, as otherwise we don't fold bitwise-binary with
compares proper anymore.  Additionally we have to take care that we
don't enter TRUTH_(AND|OR|XOR) expressions on boolified trees, as
otherwise tree-cfg will barf. Also we need to take care that types of
comparisons and TRUTH_NOT expressions are boolean one, as otherwise
again tree-cfg will detect incompatible types for those expressions.

> Thanks,
> Richard.
>
>> Regards,
>> Kai
>>
>> ChangeLog
>>
>> 2011-07-07  Kai Tietz  
>>
>>        * fold-const.c (fold_truth_not_expr): Handle
>>        one bit precision bitwise operations.
>>        (fold_range_test): Likewise.
>>        (fold_truthop): Likewise.
>>        (fold_binary_loc): Likewise.
>>        (fold_truth_andor): Function replaces truth_andor
>>        label.
>>        (fold_ternary_loc): Use truth_value_type_p instead
>>        of truth_value_p.
>>        * gimple.c (canonicalize_cond_expr_cond): Likewise.
>>        * gimplify.c (gimple_boolify): Likewise.
>>        * tree-ssa-structalias.c (find_func_aliases): Likewise.
>>        * tree-ssa-forwprop.c (truth_valued_ssa_name): Likewise.
>>        * tree.h (truth_value_type_p): New function.
>>        (truth_value_p): Implemented as macro via truth_value_type_p.
>>
>>
>> Index: gcc-head/gcc/fold-const.c
>> ===
>> --- gcc-head.orig/gcc/fold-const.c
>> +++ gcc-head/gcc/fold-const.c
>> @@ -3074,20 +3074,35 @@ fold_truth_not_expr (location_t loc, tre
>>     case INTEGER_CST:
>>       return constant_boolean_node (integer_zerop (arg), type);
>>
>> +    case BIT_AND_EXPR:
>> +      if (integer_onep (TREE_OPERAND (arg, 1)))
>> +       return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 0));
>> +      if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
>> +        return NULL_TREE;
>> +      /* fall through */
>>     case TRUTH_AND_EXPR:
>>       loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
>>       loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
>> -      return build2_loc (loc, TRUTH_OR_EXPR, type,
>> +      return build2_loc (loc, (code == BIT_AND_EXPR ? BIT_IOR_EXPR
>> +                                                   : TRUTH_OR_EXPR), type,
>>                         invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
>>                         invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
>>
>> +    case BIT_IOR_EXPR:
>> +      if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
>> +        return NULL_TREE;
>> +      /* fall through.  */
>>     case TRUTH_OR_EXPR:
>>       loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
>>       loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
>> -      return build2_loc (loc, TRUTH_AND_EXPR, type,
>> +      return build2_loc (loc, (code == BIT_IOR_EXPR ? BIT_AND_EXPR
>> +                                                   : TRUTH_AND_EXPR), type,
>>                         invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
>>                         invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
>> -
>> +    case BIT_XOR_EXPR:
>> +      if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
>> +        return NULL_TREE;
>> +      /* fall through.  */
>>     case TRUTH_XOR_EXPR:
>>       /* Here we can invert either operand.  We invert the first operand
>>         unless the second operand is a TRUTH_NOT_EXPR in which case our
>> @@ -3095,10 +3110,14 @@ fold_truth_not_expr (location_t loc, tre
>>         negation of the second operand.  */
>>
>>       if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
>> -       return build2_loc (loc, TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
>> +       return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
>> +                          TREE_OPERAND (TREE_OPERAND (arg, 1)

Re: [patch tree-optimization]: [1 of 3]: Boolify compares & more

2011-07-08 Thread Richard Guenther
On Thu, Jul 7, 2011 at 6:06 PM, Kai Tietz  wrote:
> Hello,
>
> This patch - first of series - adds to fold and some helper routines support
> for one-bit precision bitwise folding and detection.
> This patch is necessary for - next patch of series - boolification of
> comparisons.
>
> Bootstrapped and regression tested for all standard-languages (plus
> Ada and Obj-C++) on host x86_64-pc-linux-gnu.
>
> Ok for apply?

Factoring out fold_truth_andor to a function should be done separately.
A patch that does just that is pre-approved.

Otherwise the patch globs too many changes and lacks reasoning.
Why do we want to handle all this in fold when the boolification
happens only after gimplification?

Thanks,
Richard.

> Regards,
> Kai
>
> ChangeLog
>
> 2011-07-07  Kai Tietz  
>
>        * fold-const.c (fold_truth_not_expr): Handle
>        one bit precision bitwise operations.
>        (fold_range_test): Likewise.
>        (fold_truthop): Likewise.
>        (fold_binary_loc): Likewise.
>        (fold_truth_andor): Function replaces truth_andor
>        label.
>        (fold_ternary_loc): Use truth_value_type_p instead
>        of truth_value_p.
>        * gimple.c (canonicalize_cond_expr_cond): Likewise.
>        * gimplify.c (gimple_boolify): Likewise.
>        * tree-ssa-structalias.c (find_func_aliases): Likewise.
>        * tree-ssa-forwprop.c (truth_valued_ssa_name): Likewise.
>        * tree.h (truth_value_type_p): New function.
>        (truth_value_p): Implemented as macro via truth_value_type_p.
>
>
> Index: gcc-head/gcc/fold-const.c
> ===
> --- gcc-head.orig/gcc/fold-const.c
> +++ gcc-head/gcc/fold-const.c
> @@ -3074,20 +3074,35 @@ fold_truth_not_expr (location_t loc, tre
>     case INTEGER_CST:
>       return constant_boolean_node (integer_zerop (arg), type);
>
> +    case BIT_AND_EXPR:
> +      if (integer_onep (TREE_OPERAND (arg, 1)))
> +       return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 0));
> +      if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
> +        return NULL_TREE;
> +      /* fall through */
>     case TRUTH_AND_EXPR:
>       loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
>       loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
> -      return build2_loc (loc, TRUTH_OR_EXPR, type,
> +      return build2_loc (loc, (code == BIT_AND_EXPR ? BIT_IOR_EXPR
> +                                                   : TRUTH_OR_EXPR), type,
>                         invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
>                         invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
>
> +    case BIT_IOR_EXPR:
> +      if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
> +        return NULL_TREE;
> +      /* fall through.  */
>     case TRUTH_OR_EXPR:
>       loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
>       loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
> -      return build2_loc (loc, TRUTH_AND_EXPR, type,
> +      return build2_loc (loc, (code == BIT_IOR_EXPR ? BIT_AND_EXPR
> +                                                   : TRUTH_AND_EXPR), type,
>                         invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
>                         invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
> -
> +    case BIT_XOR_EXPR:
> +      if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
> +        return NULL_TREE;
> +      /* fall through.  */
>     case TRUTH_XOR_EXPR:
>       /* Here we can invert either operand.  We invert the first operand
>         unless the second operand is a TRUTH_NOT_EXPR in which case our
> @@ -3095,10 +3110,14 @@ fold_truth_not_expr (location_t loc, tre
>         negation of the second operand.  */
>
>       if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
> -       return build2_loc (loc, TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
> +       return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
> +                          TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
> +      else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BIT_NOT_EXPR
> +              && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 1))) == 1)
> +       return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
>                           TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
>       else
> -       return build2_loc (loc, TRUTH_XOR_EXPR, type,
> +       return build2_loc (loc, code, type,
>                           invert_truthvalue_loc (loc, TREE_OPERAND (arg, 0)),
>                           TREE_OPERAND (arg, 1));
>
> @@ -3116,6 +3135,11 @@ fold_truth_not_expr (location_t loc, tre
>                         invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
>                         invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
>
> +
> +    case BIT_NOT_EXPR:
> +      if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
> +        return NULL_TREE;
> +      /* fall through */
>     case TRUTH_NOT_

[patch tree-optimization]: [1 of 3]: Boolify compares & more

2011-07-07 Thread Kai Tietz
Hello,

This patch - first of series - adds to fold and some helper routines support
for one-bit precision bitwise folding and detection.
This patch is necessary for - next patch of series - boolification of
comparisons.

Bootstrapped and regression tested for all standard-languages (plus
Ada and Obj-C++) on host x86_64-pc-linux-gnu.

Ok for apply?

Regards,
Kai

ChangeLog

2011-07-07  Kai Tietz  

* fold-const.c (fold_truth_not_expr): Handle
one bit precision bitwise operations.
(fold_range_test): Likewise.
(fold_truthop): Likewise.
(fold_binary_loc): Likewise.
(fold_truth_andor): Function replaces truth_andor
label.
(fold_ternary_loc): Use truth_value_type_p instead
of truth_value_p.
* gimple.c (canonicalize_cond_expr_cond): Likewise.
* gimplify.c (gimple_boolify): Likewise.
* tree-ssa-structalias.c (find_func_aliases): Likewise.
* tree-ssa-forwprop.c (truth_valued_ssa_name): Likewise.
* tree.h (truth_value_type_p): New function.
(truth_value_p): Implemented as macro via truth_value_type_p.


Index: gcc-head/gcc/fold-const.c
===
--- gcc-head.orig/gcc/fold-const.c
+++ gcc-head/gcc/fold-const.c
@@ -3074,20 +3074,35 @@ fold_truth_not_expr (location_t loc, tre
 case INTEGER_CST:
   return constant_boolean_node (integer_zerop (arg), type);

+case BIT_AND_EXPR:
+  if (integer_onep (TREE_OPERAND (arg, 1)))
+   return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 0));
+  if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
+return NULL_TREE;
+  /* fall through */
 case TRUTH_AND_EXPR:
   loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
   loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
-  return build2_loc (loc, TRUTH_OR_EXPR, type,
+  return build2_loc (loc, (code == BIT_AND_EXPR ? BIT_IOR_EXPR
+   : TRUTH_OR_EXPR), type,
 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
 invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));

+case BIT_IOR_EXPR:
+  if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
+return NULL_TREE;
+  /* fall through.  */
 case TRUTH_OR_EXPR:
   loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc);
   loc2 = expr_location_or (TREE_OPERAND (arg, 1), loc);
-  return build2_loc (loc, TRUTH_AND_EXPR, type,
+  return build2_loc (loc, (code == BIT_IOR_EXPR ? BIT_AND_EXPR
+   : TRUTH_AND_EXPR), type,
 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
 invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));
-
+case BIT_XOR_EXPR:
+  if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
+return NULL_TREE;
+  /* fall through.  */
 case TRUTH_XOR_EXPR:
   /* Here we can invert either operand.  We invert the first operand
 unless the second operand is a TRUTH_NOT_EXPR in which case our
@@ -3095,10 +3110,14 @@ fold_truth_not_expr (location_t loc, tre
 negation of the second operand.  */

   if (TREE_CODE (TREE_OPERAND (arg, 1)) == TRUTH_NOT_EXPR)
-   return build2_loc (loc, TRUTH_XOR_EXPR, type, TREE_OPERAND (arg, 0),
+   return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
+  TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
+  else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BIT_NOT_EXPR
+  && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 1))) == 1)
+   return build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
   TREE_OPERAND (TREE_OPERAND (arg, 1), 0));
   else
-   return build2_loc (loc, TRUTH_XOR_EXPR, type,
+   return build2_loc (loc, code, type,
   invert_truthvalue_loc (loc, TREE_OPERAND (arg, 0)),
   TREE_OPERAND (arg, 1));

@@ -3116,6 +3135,11 @@ fold_truth_not_expr (location_t loc, tre
 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)),
 invert_truthvalue_loc (loc2, TREE_OPERAND (arg, 1)));

+
+case BIT_NOT_EXPR:
+  if (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg, 0))) != 1)
+return NULL_TREE;
+  /* fall through */
 case TRUTH_NOT_EXPR:
   return TREE_OPERAND (arg, 0);

@@ -3158,11 +3182,6 @@ fold_truth_not_expr (location_t loc, tre
   return build1_loc (loc, TREE_CODE (arg), type,
 invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0)));

-case BIT_AND_EXPR:
-  if (!integer_onep (TREE_OPERAND (arg, 1)))
-   return NULL_TREE;
-  return build2_loc (loc, EQ_EXPR, type, arg, build_int_cst (type, 0));
-
 case SAVE_EXPR:
   return build1_loc (loc, TRUTH_NOT_EXPR, type