+ if (TREE_CODE (arg0) == BIT_XOR_EXPR
+ && TREE_CODE (arg1) == BIT_XOR_EXPR)
+ {
+ tree arg00 = TREE_OPERAND (arg0, 0);
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ tree arg10 = TREE_OPERAND (arg1, 0);
+ tree arg11 = TREE_OPERAND (arg1, 1);
+ tree itype = TREE_TYPE (arg0);
+
+ /* Optimize (X ^ Z) op (Y ^ Z) as X op Y, and symmetries.
+ operand_equal_p guarantees no side-effects so we don't need
+ to use omit_one_operand on Z. */
+ if (operand_equal_p (arg01, arg11, 0))
+ return fold_build2 (code, type, arg00, arg10);
+ if (operand_equal_p (arg01, arg10, 0))
+ return fold_build2 (code, type, arg00, arg11);
+ if (operand_equal_p (arg00, arg11, 0))
+ return fold_build2 (code, type, arg01, arg10);
+ if (operand_equal_p (arg00, arg10, 0))
+ return fold_build2 (code, type, arg01, arg11);
+
+ /* Optimize (X ^ C1) op (Y ^ C2) as (X ^ (C1 ^ C2)) op Y. */
+ if (TREE_CODE (arg01) == INTEGER_CST
+ && TREE_CODE (arg11) == INTEGER_CST)
+ return fold_build2 (code, type,
+ fold_build2 (BIT_XOR_EXPR, itype, arg00,
+ fold_build2 (BIT_XOR_EXPR, itype,
+ arg01, arg11)),
+ arg10);
+ }
+
+ /* Attempt to simplify equality/inequality comparisons of complex
+ values. Only lower the comparison if the result is known or
+ can be simplified to a single scalar comparison. */
+ if ((TREE_CODE (arg0) == COMPLEX_EXPR
+ || TREE_CODE (arg0) == COMPLEX_CST)
+ && (TREE_CODE (arg1) == COMPLEX_EXPR
+ || TREE_CODE (arg1) == COMPLEX_CST))
+ {
+ tree real0, imag0, real1, imag1;
+ tree rcond, icond;
+
+ if (TREE_CODE (arg0) == COMPLEX_EXPR)
+ {
+ real0 = TREE_OPERAND (arg0, 0);
+ imag0 = TREE_OPERAND (arg0, 1);
+ }
+ else
+ {
+ real0 = TREE_REALPART (arg0);
+ imag0 = TREE_IMAGPART (arg0);
+ }
+
+ if (TREE_CODE (arg1) == COMPLEX_EXPR)
+ {
+ real1 = TREE_OPERAND (arg1, 0);
+ imag1 = TREE_OPERAND (arg1, 1);
+ }
+ else
+ {
+ real1 = TREE_REALPART (arg1);
+ imag1 = TREE_IMAGPART (arg1);
+ }
+
+ rcond = fold_binary (code, type, real0, real1);
+ if (rcond && TREE_CODE (rcond) == INTEGER_CST)
+ {
+ if (integer_zerop (rcond))
+ {
+ if (code == EQ_EXPR)
+ return omit_two_operands (type, boolean_false_node,
+ imag0, imag1);
+ return fold_build2 (NE_EXPR, type, imag0, imag1);
+ }
+ else
+ {
+ if (code == NE_EXPR)
+ return omit_two_operands (type, boolean_true_node,
+ imag0, imag1);
+ return fold_build2 (EQ_EXPR, type, imag0, imag1);
+ }
+ }
+
+ icond = fold_binary (code, type, imag0, imag1);
+ if (icond && TREE_CODE (icond) == INTEGER_CST)
+ {
+ if (integer_zerop (icond))
+ {
+ if (code == EQ_EXPR)
+ return omit_two_operands (type, boolean_false_node,
+ real0, real1);
+ return fold_build2 (NE_EXPR, type, real0, real1);
+ }
+ else
+ {
+ if (code == NE_EXPR)
+ return omit_two_operands (type, boolean_true_node,
+ real0, real1);
+ return fold_build2 (EQ_EXPR, type, real0, real1);
+ }
+ }
+ }
+