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, arg);

@@ -4800,7 +4819,7 @@ fold_range_test (location_t loc, enum tr
 		 tree op0, tree op1)
 {
   int or_op = (code == TRUTH_ORIF_EXPR
-	       || code == TRUTH_OR_EXPR);
+	       || code == TRUTH_OR_EXPR || code == BIT_IOR_EXPR);
   int in0_p, in1_p, in_p;
   tree low0, low1, low, high0, high1, high;
   bool strict_overflow_p = false;
@@ -5099,8 +5118,9 @@ fold_truthop (location_t loc, enum tree_
 	}
     }

-  code = ((code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR)
-	  ? TRUTH_AND_EXPR : TRUTH_OR_EXPR);
+  if (code != BIT_AND_EXPR && code != BIT_IOR_EXPR)
+    code = ((code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR)
+	    ? TRUTH_AND_EXPR : TRUTH_OR_EXPR);

   /* If the RHS can be evaluated unconditionally and its operands are
      simple, it wins to evaluate the RHS unconditionally on machines
@@ -5115,7 +5135,7 @@ fold_truthop (location_t loc, enum tree_
       && simple_operand_p (rr_arg))
     {
       /* Convert (a != 0) || (b != 0) into (a | b) != 0.  */
-      if (code == TRUTH_OR_EXPR
+      if ((code == TRUTH_OR_EXPR || code == BIT_IOR_EXPR)
 	  && lcode == NE_EXPR && integer_zerop (lr_arg)
 	  && rcode == NE_EXPR && integer_zerop (rr_arg)
 	  && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
@@ -5126,7 +5146,7 @@ fold_truthop (location_t loc, enum tree_
 			   build_int_cst (TREE_TYPE (ll_arg), 0));

       /* Convert (a == 0) && (b == 0) into (a | b) == 0.  */
-      if (code == TRUTH_AND_EXPR
+      if ((code == TRUTH_AND_EXPR || code == BIT_AND_EXPR)
 	  && lcode == EQ_EXPR && integer_zerop (lr_arg)
 	  && rcode == EQ_EXPR && integer_zerop (rr_arg)
 	  && TREE_TYPE (ll_arg) == TREE_TYPE (rl_arg)
@@ -5190,7 +5210,8 @@ fold_truthop (location_t loc, enum tree_
      fail.  However, we can convert a one-bit comparison against zero into
      the opposite comparison against that bit being set in the field.  */

-  wanted_code = (code == TRUTH_AND_EXPR ? EQ_EXPR : NE_EXPR);
+  wanted_code = ((code == TRUTH_AND_EXPR || code == BIT_AND_EXPR)
+  		 ? EQ_EXPR : NE_EXPR);
   if (lcode != wanted_code)
     {
       if (l_const && integer_zerop (l_const) && integer_pow2p (ll_mask))
@@ -9324,6 +9345,105 @@ get_pointer_modulus_and_residue (tree ex
   return 1;
 }

+/* Fold a binary bitwise/truth expression of code CODE and type TYPE
with operands
+   OP0 and OP1.  LOC is the location of the resulting expression.
+   ARG0 and ARG1 are the NOP_STRIPed results of OP0 and OP1.
+   Return the folded expression if folding is successful.  Otherwise,
+   return NULL_TREE.  */
+
+static tree
+fold_truth_andor (location_t loc, enum tree_code code, tree type,
+		  tree arg0, tree arg1, tree op0, tree op1)
+{
+  tree tem;
+
+  /* We only do these simplifications if we are optimizing.  */
+  if (!optimize)
+    return NULL_TREE;
+  /* If code is BIT_AND_EXPR or BIT_IOR_EXPR, type precision has to be one.  */
+  if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
+      && (!INTEGRAL_TYPE_P (type) || TYPE_PRECISION (type) != 1))
+    return NULL_TREE;
+
+  /* Check for things like (A || B) && (A || C).  We can convert this
+     to A || (B && C).  Note that either operator can be any of the four
+     truth and/or operations and the transformation will still be
+     valid.   Also note that we only care about order for the
+     ANDIF and ORIF operators.  If B contains side effects, this
+     might change the truth-value of A.  */
+  if (TREE_CODE (arg0) == TREE_CODE (arg1)
+      && (TREE_CODE (arg0) == TRUTH_ANDIF_EXPR
+	  || TREE_CODE (arg0) == TRUTH_ORIF_EXPR
+	  || TREE_CODE (arg0) == BIT_AND_EXPR
+	  || TREE_CODE (arg0) == BIT_IOR_EXPR
+	  || TREE_CODE (arg0) == TRUTH_AND_EXPR
+	  || TREE_CODE (arg0) == TRUTH_OR_EXPR)
+      && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg0, 1)))
+    {
+      tree a00 = TREE_OPERAND (arg0, 0);
+      tree a01 = TREE_OPERAND (arg0, 1);
+      tree a10 = TREE_OPERAND (arg1, 0);
+      tree a11 = TREE_OPERAND (arg1, 1);
+      int commutative = ((TREE_CODE (arg0) == TRUTH_OR_EXPR
+			  || TREE_CODE (arg0) == TRUTH_AND_EXPR
+			  || TREE_CODE (arg0) == BIT_AND_EXPR)
+			 && (code == TRUTH_AND_EXPR
+			     || code == TRUTH_OR_EXPR
+			     || code == BIT_IOR_EXPR));
+
+      if (operand_equal_p (a00, a10, 0))
+	return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
+			    fold_build2_loc (loc, code, type, a01, a11));
+      else if (commutative && operand_equal_p (a00, a11, 0))
+	return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
+			    fold_build2_loc (loc, code, type, a01, a10));
+      else if (commutative && operand_equal_p (a01, a10, 0))
+	return fold_build2_loc (loc, TREE_CODE (arg0), type, a01,
+			    fold_build2_loc (loc, code, type, a00, a11));
+
+      /* This case if tricky because we must either have commutative
+	 operators or else A10 must not have side-effects.  */
+
+      else if ((commutative || ! TREE_SIDE_EFFECTS (a10))
+	       && operand_equal_p (a01, a11, 0))
+	return fold_build2_loc (loc, TREE_CODE (arg0), type,
+			    fold_build2_loc (loc, code, type, a00, a10),
+			    a01);
+    }
+
+  /* See if we can build a range comparison. */
+  if (0 != (tem = fold_range_test (loc, code, type, op0, op1)))
+    return tem;
+
+  if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg0) == TRUTH_ORIF_EXPR)
+      || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg0) == TRUTH_ANDIF_EXPR))
+    {
+      tem = merge_truthop_with_opposite_arm (loc, arg0, arg1, true);
+      if (tem)
+	return fold_build2_loc (loc, code, type, tem, arg1);
+    }
+
+  if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg1) == TRUTH_ORIF_EXPR)
+      || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg1) == TRUTH_ANDIF_EXPR))
+    {
+      tem = merge_truthop_with_opposite_arm (loc, arg1, arg0, false);
+      if (tem)
+	return fold_build2_loc (loc, code, type, arg0, tem);
+    }
+
+  /* Check for the possibility of merging component references.  If our
+     lhs is another similar operation, try to merge its rhs with our
+     rhs.  Then try to merge our lhs and rhs.  */
+  if (TREE_CODE (arg0) == code
+      && 0 != (tem = fold_truthop (loc, code, type,
+				   TREE_OPERAND (arg0, 1), arg1)))
+    return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
+
+  if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
+    return tem;
+
+  return NULL_TREE;
+}

 /* Fold a binary expression of code CODE and type TYPE with operands
    OP0 and OP1.  LOC is the location of the resulting expression.
@@ -9424,21 +9544,42 @@ fold_binary_loc (location_t loc,

   if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
        || code == EQ_EXPR || code == NE_EXPR)
-      && ((truth_value_p (TREE_CODE (arg0))
-	   && (truth_value_p (TREE_CODE (arg1))
+      && (!INTEGRAL_TYPE_P (type) || TYPE_PRECISION (type) != 1)
+      && ((truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
+	   && (truth_value_type_p (TREE_CODE (arg1), TREE_TYPE (arg1))
 	       || (TREE_CODE (arg1) == BIT_AND_EXPR
 		   && integer_onep (TREE_OPERAND (arg1, 1)))))
-	  || (truth_value_p (TREE_CODE (arg1))
-	      && (truth_value_p (TREE_CODE (arg0))
+	  || (truth_value_type_p (TREE_CODE (arg1), TREE_TYPE (arg1))
+	      && (truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
 		  || (TREE_CODE (arg0) == BIT_AND_EXPR
 		      && integer_onep (TREE_OPERAND (arg0, 1)))))))
     {
       tem = fold_build2_loc (loc, code == BIT_AND_EXPR ? TRUTH_AND_EXPR
-			 : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
-			 : TRUTH_XOR_EXPR,
-			 boolean_type_node,
-			 fold_convert_loc (loc, boolean_type_node, arg0),
-			 fold_convert_loc (loc, boolean_type_node, arg1));
+			   : code == BIT_IOR_EXPR ? TRUTH_OR_EXPR
+			   : TRUTH_XOR_EXPR,
+			   boolean_type_node,
+			   fold_convert_loc (loc, boolean_type_node, arg0),
+			   fold_convert_loc (loc, boolean_type_node, arg1));
+
+      if (code == EQ_EXPR)
+	tem = invert_truthvalue_loc (loc, tem);
+
+      return fold_convert_loc (loc, type, tem);
+    }
+  if ((code == EQ_EXPR || code == NE_EXPR)
+      && ((truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
+	   && (truth_value_type_p (TREE_CODE (arg1), TREE_TYPE (arg1))
+	       || (TREE_CODE (arg1) == BIT_AND_EXPR
+		   && integer_onep (TREE_OPERAND (arg1, 1)))))
+	  || (truth_value_type_p (TREE_CODE (arg1), TREE_TYPE (arg1))
+	      && (truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
+		  || (TREE_CODE (arg0) == BIT_AND_EXPR
+		      && integer_onep (TREE_OPERAND (arg0, 1)))))))
+    {
+      tem = fold_build2_loc (loc, BIT_XOR_EXPR,
+			   boolean_type_node,
+			   fold_convert_loc (loc, boolean_type_node, arg0),
+			   fold_convert_loc (loc, boolean_type_node, arg1));

       if (code == EQ_EXPR)
 	tem = invert_truthvalue_loc (loc, tem);
@@ -10597,6 +10738,57 @@ fold_binary_loc (location_t loc,
       if (operand_equal_p (arg0, arg1, 0))
 	return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));

+      if (TYPE_PRECISION (type) == 1 && INTEGRAL_TYPE_P (type))
+        {
+	  /* If either arg is constant zero, drop it.  */
+	  if (TREE_CODE (arg0) == INTEGER_CST && integer_zerop (arg0))
+	    return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+	  if (TREE_CODE (arg1) == INTEGER_CST && integer_zerop (arg1))
+	    return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
+	  /* If second arg is constant true, result is true, but we must
+	     evaluate first arg.  */
+	  if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1))
+	    return omit_one_operand_loc (loc, type, arg1, arg0);
+	  if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
+	    return omit_one_operand_loc (loc, type, arg0, arg1);
+
+	  /* !X | X is always true.  */
+	  if ((TREE_CODE (arg0) == TRUTH_NOT_EXPR
+	       || TREE_CODE (arg0) == BIT_NOT_EXPR)
+	      && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+	    return omit_one_operand_loc (loc, type, integer_one_node, arg1);
+	  /* X | !X is always true.  */
+	  if ((TREE_CODE (arg1) == TRUTH_NOT_EXPR
+	      || TREE_CODE (arg1) == BIT_NOT_EXPR)
+	      && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+	    return omit_one_operand_loc (loc, type, integer_one_node, arg0);
+
+	  /* (X & !Y) | (!X & Y) is X ^ Y */
+	  if (TREE_CODE (arg0) == BIT_AND_EXPR
+	      && TREE_CODE (arg1) == BIT_AND_EXPR)
+	    {
+	      tree a0, a1, l0, l1, n0, n1;
+
+	      a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
+	      a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
+
+	      l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
+	      l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
+
+	      n0 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l0);
+	      n1 = fold_build1_loc (loc, TRUTH_NOT_EXPR, type, l1);
+
+	      if ((operand_equal_p (n0, a0, 0)
+		   && operand_equal_p (n1, a1, 0))
+		  || (operand_equal_p (n0, a1, 0)
+		      && operand_equal_p (n1, a0, 0)))
+		return fold_build2_loc (loc, BIT_XOR_EXPR, type, l0, n1);
+	    }
+	  tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1);
+	  if (tem)
+	    return tem;
+        }
+
       /* ~X | X is -1.  */
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
 	  && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
@@ -10758,6 +10950,24 @@ fold_binary_loc (location_t loc,
       if (operand_equal_p (arg0, arg1, 0))
 	return omit_one_operand_loc (loc, type, integer_zero_node, arg0);

+      if (TYPE_PRECISION (type) == 1 && INTEGRAL_TYPE_P (type))
+        {
+	  /* If the second arg is constant true, this is a logical inversion.  */
+	  if (integer_onep (arg1))
+	    {
+	      tem = invert_truthvalue_loc (loc, arg0);
+	      return non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+	    }
+	  /* !X ^ X is always true.  */
+	  if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+	      && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+	    return omit_one_operand_loc (loc, type, integer_one_node, arg1);
+	  /* X ^ !X is always true.  */
+	  if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+	      && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+	    return omit_one_operand_loc (loc, type, integer_one_node, arg0);
+	}
+
       /* ~X ^ X is -1.  */
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
 	  && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
@@ -10918,6 +11128,61 @@ fold_binary_loc (location_t loc,
 	return omit_one_operand_loc (loc, type, arg1, arg0);
       if (operand_equal_p (arg0, arg1, 0))
 	return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
+      /* Note that the operands of this must be ints
+	 and their values must be 0 or 1.
+	 ("true" is a fixed value perhaps depending on the language.)  */
+      /* If first arg is constant zero, return it.  */
+      if (integer_zerop (arg0))
+	return fold_convert_loc (loc, type, arg0);
+
+      if (TYPE_PRECISION (type) == 1 && INTEGRAL_TYPE_P (type))
+        {
+	  /* If either arg is constant true, drop it.  */
+	  if (TREE_CODE (arg0) == INTEGER_CST && ! integer_zerop (arg0))
+	    return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+	  if (TREE_CODE (arg1) == INTEGER_CST && ! integer_zerop (arg1)
+	      /* Preserve sequence points.  */
+	      && (code != TRUTH_ANDIF_EXPR || ! TREE_SIDE_EFFECTS (arg0)))
+	    return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
+	  /* If second arg is constant zero, result is zero, but first arg
+	     must be evaluated.  */
+	  if (integer_zerop (arg1))
+	    return omit_one_operand_loc (loc, type, arg1, arg0);
+	  /* Likewise for first arg, but note that only the TRUTH_AND_EXPR
+	     case will be handled here.  */
+	  if (integer_zerop (arg0))
+	    return omit_one_operand_loc (loc, type, arg0, arg1);
+
+	  /* !X && X is always false.  */
+	  if (TREE_CODE (arg0) == TRUTH_NOT_EXPR
+	      && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
+	    return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
+	  /* X & !X is always false.  */
+	  if (TREE_CODE (arg1) == TRUTH_NOT_EXPR
+	      && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
+	    return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
+
+	  /* A < X & A + 1 > Y ==> A < X & A >= Y.  Normally A + 1 > Y
+	     means A >= Y & A != MAX, but in this case we know that
+	     A < X <= MAX.  */
+
+	  if (!TREE_SIDE_EFFECTS (arg0)
+	      && !TREE_SIDE_EFFECTS (arg1))
+	    {
+	      tem = fold_to_nonsharp_ineq_using_bound (loc, arg0, arg1);
+	      if (tem && !operand_equal_p (tem, arg0, 0))
+		return fold_build2_loc (loc, code, type, tem, arg1);
+
+	      tem = fold_to_nonsharp_ineq_using_bound (loc, arg1, arg0);
+	      if (tem && !operand_equal_p (tem, arg1, 0))
+		return fold_build2_loc (loc, code, type, arg0, tem);
+	    }
+
+	  tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1);
+	  if (tem)
+	    return tem;
+
+	}

       /* ~X & X, (X == 0) & X, and !X & X are always zero.  */
       if ((TREE_CODE (arg0) == BIT_NOT_EXPR
@@ -12006,86 +12271,11 @@ fold_binary_loc (location_t loc,
 	    return fold_build2_loc (loc, code, type, arg0, tem);
 	}

-    truth_andor:
-      /* We only do these simplifications if we are optimizing.  */
-      if (!optimize)
-	return NULL_TREE;
-
-      /* Check for things like (A || B) && (A || C).  We can convert this
-	 to A || (B && C).  Note that either operator can be any of the four
-	 truth and/or operations and the transformation will still be
-	 valid.   Also note that we only care about order for the
-	 ANDIF and ORIF operators.  If B contains side effects, this
-	 might change the truth-value of A.  */
-      if (TREE_CODE (arg0) == TREE_CODE (arg1)
-	  && (TREE_CODE (arg0) == TRUTH_ANDIF_EXPR
-	      || TREE_CODE (arg0) == TRUTH_ORIF_EXPR
-	      || TREE_CODE (arg0) == TRUTH_AND_EXPR
-	      || TREE_CODE (arg0) == TRUTH_OR_EXPR)
-	  && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg0, 1)))
-	{
-	  tree a00 = TREE_OPERAND (arg0, 0);
-	  tree a01 = TREE_OPERAND (arg0, 1);
-	  tree a10 = TREE_OPERAND (arg1, 0);
-	  tree a11 = TREE_OPERAND (arg1, 1);
-	  int commutative = ((TREE_CODE (arg0) == TRUTH_OR_EXPR
-			      || TREE_CODE (arg0) == TRUTH_AND_EXPR)
-			     && (code == TRUTH_AND_EXPR
-				 || code == TRUTH_OR_EXPR));
-
-	  if (operand_equal_p (a00, a10, 0))
-	    return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
-				fold_build2_loc (loc, code, type, a01, a11));
-	  else if (commutative && operand_equal_p (a00, a11, 0))
-	    return fold_build2_loc (loc, TREE_CODE (arg0), type, a00,
-				fold_build2_loc (loc, code, type, a01, a10));
-	  else if (commutative && operand_equal_p (a01, a10, 0))
-	    return fold_build2_loc (loc, TREE_CODE (arg0), type, a01,
-				fold_build2_loc (loc, code, type, a00, a11));
-
-	  /* This case if tricky because we must either have commutative
-	     operators or else A10 must not have side-effects.  */
-
-	  else if ((commutative || ! TREE_SIDE_EFFECTS (a10))
-		   && operand_equal_p (a01, a11, 0))
-	    return fold_build2_loc (loc, TREE_CODE (arg0), type,
-				fold_build2_loc (loc, code, type, a00, a10),
-				a01);
-	}
-
-      /* See if we can build a range comparison.  */
-      if (0 != (tem = fold_range_test (loc, code, type, op0, op1)))
-	return tem;
-
-      if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg0) == TRUTH_ORIF_EXPR)
-	  || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg0) == TRUTH_ANDIF_EXPR))
-	{
-	  tem = merge_truthop_with_opposite_arm (loc, arg0, arg1, true);
-	  if (tem)
-	    return fold_build2_loc (loc, code, type, tem, arg1);
-	}
-
-      if ((code == TRUTH_ANDIF_EXPR && TREE_CODE (arg1) == TRUTH_ORIF_EXPR)
-	  || (code == TRUTH_ORIF_EXPR && TREE_CODE (arg1) == TRUTH_ANDIF_EXPR))
-	{
-	  tem = merge_truthop_with_opposite_arm (loc, arg1, arg0, false);
-	  if (tem)
-	    return fold_build2_loc (loc, code, type, arg0, tem);
-	}
-
-      /* Check for the possibility of merging component references.  If our
-	 lhs is another similar operation, try to merge its rhs with our
-	 rhs.  Then try to merge our lhs and rhs.  */
-      if (TREE_CODE (arg0) == code
-	  && 0 != (tem = fold_truthop (loc, code, type,
-				       TREE_OPERAND (arg0, 1), arg1)))
-	return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
-
-      if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
-	return tem;
+      tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1);
+      if (tem)
+        return tem;

       return NULL_TREE;
-
     case TRUTH_ORIF_EXPR:
       /* Note that the operands of this must be ints
 	 and their values must be 0 or true.
@@ -12140,7 +12330,11 @@ fold_binary_loc (location_t loc,
 		  && operand_equal_p (n1, a0, 0)))
 	    return fold_build2_loc (loc, TRUTH_XOR_EXPR, type, l0, n1);
 	}
-      goto truth_andor;
+      tem = fold_truth_andor (loc, code, type, arg0, arg1, op0, op1);
+      if (tem)
+        return tem;
+
+      return NULL_TREE;

     case TRUTH_XOR_EXPR:
       /* If the second arg is constant zero, drop it.  */
@@ -13401,7 +13595,7 @@ fold_ternary_loc (location_t loc, enum t

       /* If the second operand is simpler than the third, swap them
 	 since that produces better jump optimization results.  */
-      if (truth_value_p (TREE_CODE (arg0))
+      if (truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0))
 	  && tree_swap_operands_p (op1, op2, false))
 	{
 	  location_t loc0 = expr_location_or (arg0, loc);
@@ -13427,7 +13621,7 @@ fold_ternary_loc (location_t loc, enum t
 	 over COND_EXPR in cases such as floating point comparisons.  */
       if (integer_zerop (op1)
 	  && integer_onep (op2)
-	  && truth_value_p (TREE_CODE (arg0)))
+	  && truth_value_type_p (TREE_CODE (arg0), TREE_TYPE (arg0)))
 	return pedantic_non_lvalue_loc (loc,
 				    fold_convert_loc (loc, type,
 					      invert_truthvalue_loc (loc,
Index: gcc-head/gcc/gimple.c
===================================================================
--- gcc-head.orig/gcc/gimple.c
+++ gcc-head/gcc/gimple.c
@@ -3160,7 +3160,8 @@ canonicalize_cond_expr_cond (tree t)
 {
   /* Strip conversions around boolean operations.  */
   if (CONVERT_EXPR_P (t)
-      && truth_value_p (TREE_CODE (TREE_OPERAND (t, 0))))
+      && truth_value_type_p (TREE_CODE (TREE_OPERAND (t, 0)),
+			     TREE_TYPE (TREE_OPERAND (t, 0))))
     t = TREE_OPERAND (t, 0);

   /* For !x use x == 0.  */
Index: gcc-head/gcc/gimplify.c
===================================================================
--- gcc-head.orig/gcc/gimplify.c
+++ gcc-head/gcc/gimplify.c
@@ -2837,7 +2837,7 @@ gimple_boolify (tree expr)
 	      if (TREE_CODE (arg) == NOP_EXPR
 		  && TREE_TYPE (arg) == TREE_TYPE (call))
 		arg = TREE_OPERAND (arg, 0);
-	      if (truth_value_p (TREE_CODE (arg)))
+	      if (truth_value_type_p (TREE_CODE (arg), TREE_TYPE (arg)))
 		{
 		  arg = gimple_boolify (arg);
 		  CALL_EXPR_ARG (call, 0)
Index: gcc-head/gcc/tree-ssa-structalias.c
===================================================================
--- gcc-head.orig/gcc/tree-ssa-structalias.c
+++ gcc-head/gcc/tree-ssa-structalias.c
@@ -4416,7 +4416,8 @@ find_func_aliases (gimple origt)
 			 && !POINTER_TYPE_P (TREE_TYPE (rhsop))))
 		   || gimple_assign_single_p (t))
 	    get_constraint_for_rhs (rhsop, &rhsc);
-	  else if (truth_value_p (code))
+	  else if (truth_value_type_p (code,
+				       TREE_TYPE (lhsop)))
 	    /* Truth value results are not pointer (parts).  Or at least
 	       very very unreasonable obfuscation of a part.  */
 	    ;
Index: gcc-head/gcc/tree.h
===================================================================
--- gcc-head.orig/gcc/tree.h
+++ gcc-head/gcc/tree.h
@@ -5309,13 +5309,22 @@ extern tree combine_comparisons (locatio
 extern void debug_fold_checksum (const_tree);

 /* Return nonzero if CODE is a tree code that represents a truth value.  */
+#define truth_value_p(CODE)  truth_value_type_p ((CODE), NULL_TREE)
+
+/* Return nonzero if CODE is a tree code that represents a truth value.
+   If TYPE is an integral type, unsigned, and has precision of one, then
+   additionally return for bitwise-binary and bitwise-invert nonzero.  */
 static inline bool
-truth_value_p (enum tree_code code)
+truth_value_type_p (enum tree_code code, tree type)
 {
   return (TREE_CODE_CLASS (code) == tcc_comparison
 	  || code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
 	  || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
-	  || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR);
+	  || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR
+	  || ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
+	       || code == BIT_XOR_EXPR || code == BIT_NOT_EXPR)
+	      && type && INTEGRAL_TYPE_P (type)
+	      && TYPE_PRECISION (type) == 1 && TYPE_UNSIGNED (type)));
 }


Index: gcc-head/gcc/tree-ssa-forwprop.c
===================================================================
--- gcc-head.orig/gcc/tree-ssa-forwprop.c
+++ gcc-head/gcc/tree-ssa-forwprop.c
@@ -1668,7 +1668,7 @@ truth_valued_ssa_name (tree name)
     return true;
   def = SSA_NAME_DEF_STMT (name);
   if (is_gimple_assign (def))
-    return truth_value_p (gimple_assign_rhs_code (def));
+    return truth_value_type_p (gimple_assign_rhs_code (def), type);
   return false;
 }

