===================================================================
@@ -23,20 +23,21 @@ along with GCC; see the file COPYING3.
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "flags.h"
#include "function.h"
#include "dumpfile.h"
#include "tree-flow.h"
#include "tree-ssa-propagate.h"
#include "target.h"
#include "gimple-fold.h"
+#include "langhooks.h"
/* Return true when DECL can be referenced from current unit.
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
We can get declarations that are not possible to reference for various
reasons:
1) When analyzing C++ virtual tables.
C++ virtual tables do have known constructors even
when they are keyed to other compilation unit.
Those tables can contain pointers to methods and vars
@@ -1685,41 +1686,51 @@ and_var_with_comparison_1 (gimple stmt,
(OP1A CODE1 OP1B) and (OP2A CODE2 OP2B), respectively.
If this can be done without constructing an intermediate value,
return the resulting tree; otherwise NULL_TREE is returned.
This function is deliberately asymmetric as it recurses on SSA_DEFs
in the first comparison but not the second. */
static tree
and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b)
{
+ tree truth_type = boolean_type_node;
+ if (TREE_CODE (TREE_TYPE (op1a)) == VECTOR_TYPE)
+ {
+ tree vec_type = TREE_TYPE (op1a);
+ tree elem = lang_hooks.types.type_for_size
+ (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (vec_type))), 0);
+ truth_type = build_opaque_vector_type (elem,
+ TYPE_VECTOR_SUBPARTS (vec_type));
+ }
+
/* First check for ((x CODE1 y) AND (x CODE2 y)). */
if (operand_equal_p (op1a, op2a, 0)
&& operand_equal_p (op1b, op2b, 0))
{
/* Result will be either NULL_TREE, or a combined comparison. */
tree t = combine_comparisons (UNKNOWN_LOCATION,
TRUTH_ANDIF_EXPR, code1, code2,
- boolean_type_node, op1a, op1b);
+ truth_type, op1a, op1b);
if (t)
return t;
}
/* Likewise the swapped case of the above. */
if (operand_equal_p (op1a, op2b, 0)
&& operand_equal_p (op1b, op2a, 0))
{
/* Result will be either NULL_TREE, or a combined comparison. */
tree t = combine_comparisons (UNKNOWN_LOCATION,
TRUTH_ANDIF_EXPR, code1,
swap_tree_comparison (code2),
- boolean_type_node, op1a, op1b);
+ truth_type, op1a, op1b);
if (t)
return t;
}
/* If both comparisons are of the same value against constants, we might
be able to merge them. */
if (operand_equal_p (op1a, op2a, 0)
&& TREE_CODE (op1b) == INTEGER_CST
&& TREE_CODE (op2b) == INTEGER_CST)
{
@@ -2147,41 +2158,51 @@ or_var_with_comparison_1 (gimple stmt,
(OP1A CODE1 OP1B) and (OP2A CODE2 OP2B), respectively.
If this can be done without constructing an intermediate value,
return the resulting tree; otherwise NULL_TREE is returned.
This function is deliberately asymmetric as it recurses on SSA_DEFs
in the first comparison but not the second. */
static tree
or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b)
{
+ tree truth_type = boolean_type_node;
+ if (TREE_CODE (TREE_TYPE (op1a)) == VECTOR_TYPE)
+ {
+ tree vec_type = TREE_TYPE (op1a);
+ tree elem = lang_hooks.types.type_for_size
+ (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (vec_type))), 0);
+ truth_type = build_opaque_vector_type (elem,
+ TYPE_VECTOR_SUBPARTS (vec_type));
+ }
+
/* First check for ((x CODE1 y) OR (x CODE2 y)). */
if (operand_equal_p (op1a, op2a, 0)
&& operand_equal_p (op1b, op2b, 0))
{
/* Result will be either NULL_TREE, or a combined comparison. */
tree t = combine_comparisons (UNKNOWN_LOCATION,
TRUTH_ORIF_EXPR, code1, code2,
- boolean_type_node, op1a, op1b);
+ truth_type, op1a, op1b);
if (t)
return t;
}
/* Likewise the swapped case of the above. */
if (operand_equal_p (op1a, op2b, 0)
&& operand_equal_p (op1b, op2a, 0))
{
/* Result will be either NULL_TREE, or a combined comparison. */
tree t = combine_comparisons (UNKNOWN_LOCATION,
TRUTH_ORIF_EXPR, code1,
swap_tree_comparison (code2),
- boolean_type_node, op1a, op1b);
+ truth_type, op1a, op1b);
if (t)
return t;
}
/* If both comparisons are of the same value against constants, we might
be able to merge them. */
if (operand_equal_p (op1a, op2a, 0)
&& TREE_CODE (op1b) == INTEGER_CST
&& TREE_CODE (op2b) == INTEGER_CST)
{
===================================================================
@@ -3978,21 +3978,29 @@ cp_build_binary_op (location_t location,
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
result_type = boolean_type_node;
break;
/* Shift operations: result has same type as first operand;
always convert second operand to int.
Also set SHORT_SHIFT if shifting rightward. */
case RSHIFT_EXPR:
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+ && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
if (TREE_CODE (op1) == INTEGER_CST)
{
if (tree_int_cst_lt (op1, integer_zero_node))
{
if ((complain & tf_warning)
&& c_inhibit_evaluation_warnings == 0)
warning (0, "right shift count is negative");
}
@@ -4007,21 +4015,29 @@ cp_build_binary_op (location_t location,
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = cp_convert (integer_type_node, op1, complain);
/* Avoid converting op1 to result_type later. */
converted = 1;
}
break;
case LSHIFT_EXPR:
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+ && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
if (TREE_CODE (op1) == INTEGER_CST)
{
if (tree_int_cst_lt (op1, integer_zero_node))
{
if ((complain & tf_warning)
&& c_inhibit_evaluation_warnings == 0)
warning (0, "left shift count is negative");
}
@@ -4065,20 +4081,22 @@ cp_build_binary_op (location_t location,
}
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = cp_convert (integer_type_node, op1, complain);
}
break;
case EQ_EXPR:
case NE_EXPR:
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+ goto vector_compare;
if ((complain & tf_warning)
&& (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1)))
warning (OPT_Wfloat_equal,
"comparing floating point with == or != is unsafe");
if ((complain & tf_warning)
&& ((TREE_CODE (orig_op0) == STRING_CST && !integer_zerop (op1))
|| (TREE_CODE (orig_op1) == STRING_CST && !integer_zerop (op0))))
warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour");
build_type = boolean_type_node;
@@ -4307,20 +4325,49 @@ cp_build_binary_op (location_t location,
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
if (TREE_CODE (orig_op0) == STRING_CST
|| TREE_CODE (orig_op1) == STRING_CST)
{
if (complain & tf_warning)
warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour");
}
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+ {
+ vector_compare:
+ tree intt;
+ if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0),
+ TREE_TYPE (type1)))
+ {
+ error_at (location, "comparing vectors with different "
+ "element types");
+ inform (location, "operand types are %qT and %qT", type0, type1);
+ return error_mark_node;
+ }
+
+ if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+ {
+ error_at (location, "comparing vectors with different "
+ "number of elements");
+ inform (location, "operand types are %qT and %qT", type0, type1);
+ return error_mark_node;
+ }
+
+ /* Always construct signed integer vector type. */
+ intt = c_common_type_for_size (GET_MODE_BITSIZE
+ (TYPE_MODE (TREE_TYPE (type0))), 0);
+ result_type = build_opaque_vector_type (intt,
+ TYPE_VECTOR_SUBPARTS (type0));
+ converted = 1;
+ break;
+ }
build_type = boolean_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|| code0 == ENUMERAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == ENUMERAL_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
result_type = composite_pointer_type (type0, type1, op0, op1,
CPO_COMPARISON, complain);
else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))
===================================================================
@@ -1,18 +1,19 @@
/* { dg-do compile } */
+/* { dg-prune-output "in evaluation of" } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
int main (int argc, char *argv[]) {
vector(4, float) vfloat0 = {1., 2., 3., 4.};
vector(4, float) vfloat1 = {1., 2., 3., 4.};
vector(4, int) vint = {1, 1, 1, 1 };
vint <<= vfloat0; /* { dg-error "nvalid operands to binary <<" } */
vfloat0 >>= vint; /* { dg-error "nvalid operands to binary >>" } */
- vfloat0 <<= vfloat1; /* { dg-error "nvalid operands to binary <<" } */
+ vfloat0 <<= vfloat1; /* { dg-error "nvalid operands" } */
return 0;
}
===================================================================
@@ -1,16 +1,16 @@
/* { dg-do compile } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
int main (int argc, char *argv[]) {
- vector(8, short) v0 = {argc,2,3,4,5,6,7};
+ vector(8, short) v0 = {(short)argc,2,3,4,5,6,7};
short sc;
- scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */
+ scalar1 <<= v0; /* { dg-error "scalar1.*(undeclared|was not declared)" } */
return 0;
}
===================================================================
@@ -1,19 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-mabi=altivec" { target { { powerpc*-*-linux* } && ilp32 } } } */
+/* { dg-prune-output "operand types are" } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
void
foo (vector (4, int) x, vector (4, float) y)
{
vector (4, int) p4;
vector (4, int) r4;
vector (4, unsigned int) q4;
vector (8, int) r8;
vector (4, float) f4;
r4 = x > y; /* { dg-error "comparing vectors with different element types" } */
- r8 = (x != p4); /* { dg-error "incompatible types when assigning to type" } */
+ r8 = (x != p4); /* { dg-error "incompatible types when assigning to type|cannot convert" } */
r8 == r4; /* { dg-error "comparing vectors with different number of elements" } */
}
===================================================================
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef int v4i __attribute__((vector_size(4*sizeof(int))));
+
+// fold should not turn (vec_other)(x<y) into (x<y)?vec_other(-1):vec_other(0).
+
+void use (v4i const *z);
+
+void
+f (v4i *x, v4i *y)
+{
+ v4i const zz = *x < *y;
+ use (&zz);
+}
+
+// Optimizations shouldn't introduce a boolean type in there
+
+void
+g (v4i *x, v4i const *y, v4i *z, v4i *t)
+{
+ *z = *x < *y | *x == *y;
+ *t = *x < *y & *x > *y;
+}
+
Property changes on: gcc/testsuite/c-c++-common/vector-compare-3.c
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision URL
Added: svn:eol-style
+ native
===================================================================
@@ -1,11 +1,12 @@
/* { dg-do compile } */
+/* { dg-prune-output "in evaluation of" } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
int main (int argc, char *argv[]) {
vector(4,char) vchar = {1,2,3,4};
vector(4, int) vint = {1,1,1,1};
vint <<= vchar; /* { dg-error "nvalid operands to binary <<" } */
vchar >>= vint; /* { dg-error "nvalid operands to binary >>" } */
===================================================================
@@ -1,10 +1,11 @@
+/* { dg-do run } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
#define check_compare(count, res, i0, i1, op, fmt) \
do { \
int __i; \
for (__i = 0; __i < count; __i ++) { \
if ((res)[__i] != ((i0)[__i] op (i1)[__i] ? -1 : 0)) \
{ \
__builtin_printf ("%i != ((" fmt " " #op " " fmt " ? -1 : 0) ", \
@@ -31,76 +32,76 @@ do { \
} while (0)
int main (int argc, char *argv[]) {
#define INT int
vector (4, INT) i0;
vector (4, INT) i1;
vector (4, int) ires;
int i;
- i0 = (vector (4, INT)){argc, 1, 2, 10};
+ i0 = (vector (4, INT)){(INT)argc, 1, 2, 10};
i1 = (vector (4, INT)){0, 3, 2, (INT)-23};
test (4, i0, i1, ires, "%i");
#undef INT
#define INT unsigned int
vector (4, int) ures;
vector (4, INT) u0;
vector (4, INT) u1;
- u0 = (vector (4, INT)){argc, 1, 2, 10};
+ u0 = (vector (4, INT)){(INT)argc, 1, 2, 10};
u1 = (vector (4, INT)){0, 3, 2, (INT)-23};
test (4, u0, u1, ures, "%u");
#undef INT
#define SHORT short
vector (8, SHORT) s0;
vector (8, SHORT) s1;
vector (8, short) sres;
- s0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
+ s0 = (vector (8, SHORT)){(SHORT)argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
s1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
test (8, s0, s1, sres, "%i");
#undef SHORT
#define SHORT unsigned short
vector (8, SHORT) us0;
vector (8, SHORT) us1;
vector (8, short) usres;
- us0 = (vector (8, SHORT)){argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
+ us0 = (vector (8, SHORT)){(SHORT)argc, 1, 2, 10, 6, 87, (SHORT)-5, 2};
us1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
test (8, us0, us1, usres, "%u");
#undef SHORT
#define CHAR signed char
vector (16, CHAR) c0;
vector (16, CHAR) c1;
vector (16, signed char) cres;
- c0 = (vector (16, CHAR)){argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \
- argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 };
+ c0 = (vector (16, CHAR)){(CHAR)argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \
+ (CHAR)argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 };
c1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \
0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0};
test (16, c0, c1, cres, "%i");
#undef CHAR
#define CHAR unsigned char
vector (16, CHAR) uc0;
vector (16, CHAR) uc1;
vector (16, signed char) ucres;
- uc0 = (vector (16, CHAR)){argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \
- argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 };
+ uc0 = (vector (16, CHAR)){(CHAR)argc, 1, 2, 10, 6, 87, (CHAR)-5, 2, \
+ (CHAR)argc, 1, 2, 10, 6, 87, (CHAR)-5, 2 };
uc1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \
0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0};
test (16, uc0, uc1, ucres, "%u");
#undef CHAR
/* Float comparison. */
vector (4, float) f0;
vector (4, float) f1;
__typeof (f0 == f1) ifres;
===================================================================
@@ -1,10 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-Wno-psabi" } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
/* Check that constant folding in
these simple cases works. */
vector (4, int)
foo (vector (4, int) x)
{
return (x == x) + (x != x) + (x > x)
+ (x < x) + (x >= x) + (x <= x);
===================================================================
@@ -1,10 +1,11 @@
+/* { dg-do run } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
#define uint unsigned int
int main (int argc, char *argv[]) {
vector(4, uint) vuint = { 1, 2, 3, 4};
vector(4, int) vint0 = { 1, 1, 1, 1};
vector(4, int) vint1 = {-1, -1, -1, -1};
===================================================================
@@ -1,11 +1,11 @@
-/* dg-do run */
+/* { dg-do run } */
#define vector __attribute__((vector_size(sizeof(int)*4) ))
/* Check to make sure that we extract and insert the vector at the same
location for vector subscripting and that vectors layout are the same
as arrays. */
struct TV4
{
vector int v;
};
===================================================================
@@ -1,10 +1,11 @@
+/* { dg-do run } */
#define vector __attribute__((vector_size(sizeof(int)*4) ))
/* Check to make sure that we extract and insert the vector at the same
location for vector subscripting (with constant indexes) and
that vectors layout are the same as arrays. */
struct TV4
{
vector int v;
};
===================================================================
@@ -1,29 +1,30 @@
+/* { dg-do run } */
#define vector __attribute__((vector_size(sizeof(int)*4) ))
static vector int allones = {1, 1, 1, 1};
static vector int allzeros = {0, 0, 0, 0};
static vector int numbers = {0, 1, 2, 3};
static vector int numbersleftshiftallones = {0, 2, 4, 6};
static vector int numbersrightshiftallones = {0, 0, 1, 1};
static vector unsigned int uallones = {1, 1, 1, 1};
static vector unsigned int uallzeros = {0, 0, 0, 0};
static vector unsigned int unumbers = {0, 1, 2, 3};
static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
#define TEST(result, expected) \
do { \
- typeof(result) result1 = result; \
+ __typeof__(result) result1 = result; \
if(sizeof (result1) != sizeof (expected)) \
__builtin_abort (); \
if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
__builtin_abort (); \
}while (0);
int main(void)
{
vector int result;
TEST ((numbers << allzeros), numbers);
===================================================================
@@ -1,11 +1,11 @@
-/* dg-do run */
+/* { dg-do run } */
#define vector __attribute__((vector_size(16) ))
/* Check whether register declaration of vector type still
allow us to subscript this type. */
typedef vector short myvec_t;
struct vec_s {
vector short member;
};
===================================================================
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu++11 -Wall" } */
+
+// Check that we can compare vector types that really are the same through
+// typedefs.
+
+typedef float v4f __attribute__((vector_size(4*sizeof(float))));
+
+template <class T> void eat (T&&) {}
+
+template <class T, int n>
+struct Vec
+{
+ typedef T type __attribute__((vector_size(4*sizeof(T))));
+
+ template <class U>
+ static void fun (type const& t, U& u) { eat (t > u); }
+};
+
+long long
+f (v4f *x, v4f const *y)
+{
+ return ((*x < *y) | (*x <= *y))[2];
+}
+
+int main ()
+{
+ v4f x = {0,1,2,3};
+ Vec<const volatile float,4>::type f = {-1,5,2,3.1};
+ auto c = (x == f) == (x >= x);
+ eat (c[3]);
+ Vec<const volatile float,4>::fun (f, x);
+ Vec<const volatile float,4>::fun (x, f);
+ Vec<const volatile float,4>::fun (f, f);
+ Vec<const volatile float,4>::fun (x, x);
+}
Property changes on: gcc/testsuite/g++.dg/other/vector-compare.C
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision URL
Added: svn:eol-style
+ native
===================================================================
@@ -7764,21 +7764,21 @@ fold_unary_loc (location_t loc, enum tre
/* If we have (type) (a CMP b) and type is an integral type, return
new expression involving the new type. Canonicalize
(type) (a CMP b) to (a CMP b) ? (type) true : (type) false for
non-integral type.
Do not fold the result as that would not simplify further, also
folding again results in recursions. */
if (TREE_CODE (type) == BOOLEAN_TYPE)
return build2_loc (loc, TREE_CODE (op0), type,
TREE_OPERAND (op0, 0),
TREE_OPERAND (op0, 1));
- else if (!INTEGRAL_TYPE_P (type))
+ else if (!INTEGRAL_TYPE_P (type) && TREE_CODE (type) != VECTOR_TYPE)
return build3_loc (loc, COND_EXPR, type, op0,
constant_boolean_node (true, type),
constant_boolean_node (false, type));
}
/* Handle cases of two conversions in a row. */
if (CONVERT_EXPR_P (op0))
{
tree inside_type = TREE_TYPE (TREE_OPERAND (op0, 0));
tree inter_type = TREE_TYPE (op0);
@@ -9822,20 +9822,21 @@ fold_binary_loc (location_t loc,
Before we do that, see if this is a BIT_AND_EXPR or a BIT_IOR_EXPR,
one of the operands is a comparison and the other is a comparison, a
BIT_AND_EXPR with the constant 1, or a truth value. In that case, the
code below would make the expression more complex. Change it to a
TRUTH_{AND,OR}_EXPR. Likewise, convert a similar NE_EXPR to
TRUTH_XOR_EXPR and an EQ_EXPR to the inversion of a TRUTH_XOR_EXPR. */
if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR
|| code == EQ_EXPR || code == NE_EXPR)
+ && TREE_CODE (type) != VECTOR_TYPE
&& ((truth_value_p (TREE_CODE (arg0))
&& (truth_value_p (TREE_CODE (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))
|| (TREE_CODE (arg0) == BIT_AND_EXPR
&& integer_onep (TREE_OPERAND (arg0, 1)))))))
{
tem = fold_build2_loc (loc, code == BIT_AND_EXPR ? TRUTH_AND_EXPR