From patchwork Fri Sep 21 18:32:17 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 185874 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 5D6A32C007C for ; Sat, 22 Sep 2012 04:32:47 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1348857168; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Date:From:To:cc:Subject:Message-ID:User-Agent:MIME-Version: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=NNEUlVz jabekinDEpnFvOzN3xS8=; b=J8Vq2wB6y1jvtjn5ytk2S0r/gT/ju/ue650ModT UMqxZHGnLCPsZNkEXNqHFbWTuAjtc0h6oq0yeBKRIDXDUEAgw+bdi+DsUC7wgbnH o6GemfMmN0Jt2tDe7MB7pIMP7bnih7Gr+deUXr32/vC+aFlrSsUiTHaO+6Rgjd7Q KFiM= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Date:From:To:cc:Subject:Message-ID:User-Agent:MIME-Version:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=WABXWz+425iZIfZxRv3+PKBwsw3zEZow7m+PJFPluySL5ZmV5Qe45ZJFsn4f+E 076TSDFDbr2plAEmVi46xBB+/m1akzzSulqR5jgKYvtkOcCmrjf+VJWbEFz3MMFc L6QRfW2uXPrCpCXWZNFBuPvb3gmIcMzOkladyPvhwlESU=; Received: (qmail 11275 invoked by alias); 21 Sep 2012 18:32:43 -0000 Received: (qmail 11240 invoked by uid 22791); 21 Sep 2012 18:32:38 -0000 X-SWARE-Spam-Status: No, hits=-7.1 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, TW_BJ, TW_TM X-Spam-Check-By: sourceware.org Received: from mail4-relais-sop.national.inria.fr (HELO mail4-relais-sop.national.inria.fr) (192.134.164.105) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 21 Sep 2012 18:32:19 +0000 Received: from stedding.saclay.inria.fr ([193.55.250.194]) by mail4-relais-sop.national.inria.fr with ESMTP/TLS/DHE-RSA-AES128-SHA; 21 Sep 2012 20:32:17 +0200 Received: from glisse (helo=localhost) by stedding.saclay.inria.fr with local-esmtp (Exim 4.80) (envelope-from ) id 1TF81R-0002fN-4K; Fri, 21 Sep 2012 20:32:17 +0200 Date: Fri, 21 Sep 2012 20:32:17 +0200 (CEST) From: Marc Glisse To: gcc-patches@gcc.gnu.org cc: jason@redhat.com Subject: [C++] Mixed scalar-vector operations Message-ID: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello, this patch adds mixed scalar-vector operations to the C++ front-end. It also adds a few operators to the C front-end (comparisons in particular). This patch is mostly an import from the C front-end (with the maybe_const stuff removed). 2012-09-22 Marc Glisse PR c++/54427 c/ * c-typeck.c: Include c-common.h. (enum stv_conv): Moved to c-common.h. (scalar_to_vector): Moved to c-common.c. * Make-lang.in: c-typeck.c depends on c-common.h. c-family/ * c-common.c (scalar_to_vector): Moved from c-typeck.c. Support more operations. * c-common.h (enum stv_conv): Moved from c-typeck.c. (scalar_to_vector): Declare. cp/ * typeck.c (cp_build_binary_op): Handle mixed scalar-vector operations. [LSHIFT_EXPR, RSHIFT_EXPR]: Likewise. gcc/ * fold-const.c (fold_binary_loc): Use build_zero_cst instead of build_int_cst for a potential vector. testsuite/ * c-c++-common/vector-scalar.c: New testcase. * g++.dg/ext/vector5.C: This is not an error anymore. * gcc.dg/init-vec-1.c: Move ... * c-c++-common/init-vec-1.c: ... here. Adapt error message. * gcc.c-torture/execute/vector-shift1.c: Move ... * c-c++-common/torture/vector-shift1.c: ... here. * gcc.dg/scal-to-vec1.c: Move ... * c-c++-common/scal-to-vec1.c: ... here. Avoid narrowing for C++11. Adapt error message. * gcc.dg/convert-vec-1.c: Move ... * c-c++-common/convert-vec-1.c: ... here. * gcc.dg/scal-to-vec2.c: Move ... * c-c++-common/scal-to-vec2.c: ... here. Index: c-family/c-common.c =================================================================== --- c-family/c-common.c (revision 191613) +++ c-family/c-common.c (working copy) @@ -11147,11 +11147,105 @@ convert_vector_to_pointer_for_subscript c_common_mark_addressable_vec (*vecp); type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); type = build_pointer_type (type); type1 = build_pointer_type (TREE_TYPE (*vecp)); *vecp = build1 (ADDR_EXPR, type1, *vecp); *vecp = convert (type, *vecp); } } +/* Convert scalar to vector for the range of operations. */ +enum stv_conv +scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1) +{ + tree type0 = TREE_TYPE (op0); + tree type1 = TREE_TYPE (op1); + bool integer_only_op = false; + enum stv_conv ret = stv_firstarg; + + gcc_assert (TREE_CODE (type0) == VECTOR_TYPE + || TREE_CODE (type1) == VECTOR_TYPE); + switch (code) + { + case RSHIFT_EXPR: + case LSHIFT_EXPR: + if (TREE_CODE (type0) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) + { + if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) + { + error_at (loc, "conversion of scalar to vector " + "involves truncation"); + return stv_error; + } + else + return stv_firstarg; + } + break; + + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case BIT_AND_EXPR: + integer_only_op = true; + /* ... fall through ... */ + + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + case EXACT_DIV_EXPR: + case TRUNC_MOD_EXPR: + case FLOOR_MOD_EXPR: + case RDIV_EXPR: + case EQ_EXPR: + case NE_EXPR: + case LE_EXPR: + case GE_EXPR: + case LT_EXPR: + case GT_EXPR: + /* What about UNLT_EXPR? */ + if (TREE_CODE (type0) == VECTOR_TYPE) + { + tree tmp; + ret = stv_secondarg; + /* Swap TYPE0 with TYPE1 and OP0 with OP1 */ + tmp = type0; type0 = type1; type1 = tmp; + tmp = op0; op0 = op1; op1 = tmp; + } + + if (TREE_CODE (type0) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) + { + if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) + { + error_at (loc, "conversion of scalar to vector " + "involves truncation"); + return stv_error; + } + return ret; + } + else if (!integer_only_op + /* Allow integer --> real conversion if safe. */ + && (TREE_CODE (type0) == REAL_TYPE + || TREE_CODE (type0) == INTEGER_TYPE) + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1))) + { + if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) + { + error_at (loc, "conversion of scalar to vector " + "involves truncation"); + return stv_error; + } + return ret; + } + default: + break; + } + + return stv_nothing; +} + #include "gt-c-family-c-common.h" Index: c-family/c-common.h =================================================================== --- c-family/c-common.h (revision 191613) +++ c-family/c-common.h (working copy) @@ -1116,11 +1116,22 @@ struct GTY(()) tree_userdef_literal { #define USERDEF_LITERAL_NUM_STRING(NODE) \ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string) #define USERDEF_LITERAL_TYPE(NODE) \ (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE))) extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string); extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree); +/* Possibe cases of scalar_to_vector conversion. */ +enum stv_conv { + stv_error, /* Error occured. */ + stv_nothing, /* Nothing happened. */ + stv_firstarg, /* First argument must be expanded. */ + stv_secondarg /* Second argument must be expanded. */ +}; + +extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code, + tree op0, tree op1); + #endif /* ! GCC_C_COMMON_H */ Index: testsuite/g++.dg/ext/vector5.C =================================================================== --- testsuite/g++.dg/ext/vector5.C (revision 191613) +++ testsuite/g++.dg/ext/vector5.C (working copy) @@ -1,8 +1,8 @@ // PR c++/30022 // { dg-do compile } void foo() { int __attribute__((vector_size(8))) v; - v = 1/v; // { dg-error "invalid operands of types" } + v = 1/v; } Index: testsuite/c-c++-common/init-vec-1.c =================================================================== --- testsuite/c-c++-common/init-vec-1.c (revision 191610) +++ testsuite/c-c++-common/init-vec-1.c (working copy) @@ -1,4 +1,4 @@ /* Don't ICE or emit spurious errors when init a vector with a scalar. */ /* { dg-do compile } */ typedef float v2sf __attribute__ ((vector_size (8))); -v2sf a = 0.0; /* { dg-error "incompatible types" } */ +v2sf a = 0.0; /* { dg-error "incompatible types|cannot convert" } */ Index: testsuite/c-c++-common/torture/vector-shift1.c =================================================================== --- testsuite/c-c++-common/torture/vector-shift1.c (revision 191610) +++ testsuite/c-c++-common/torture/vector-shift1.c (working copy) @@ -1,10 +1,11 @@ +/* { dg-do run } */ #define vector __attribute__((vector_size(8*sizeof(short)))) int main (int argc, char *argv[]) { vector short v0 = {argc,2,3,4,5,6,7}; vector short v1 = {2,2,2,2,2,2,2}; vector short r1,r2,r3,r4; int i = 8; r1 = v0 << 1; r2 = v0 >> 1; Index: testsuite/c-c++-common/scal-to-vec1.c =================================================================== --- testsuite/c-c++-common/scal-to-vec1.c (revision 191610) +++ testsuite/c-c++-common/scal-to-vec1.c (working copy) @@ -6,21 +6,21 @@ __attribute__((vector_size((elcount)*sizeof(type)))) type #define vidx(type, vec, idx) (*((type *) &(vec) + idx)) extern float sfl; extern int sint; extern long long sll; int main (int argc, char *argv[]) { - vector(8, short) v0 = {argc, 1,2,3,4,5,6,7}; + vector(8, short) v0 = {(short)argc, 1,2,3,4,5,6,7}; vector(8, short) v1; vector(4, float) f0 = {1., 2., 3., 4.}; vector(4, float) f1, f2; vector(4, int) i0 = {1,2,3,4}; vector(4, int) i1, i2; int i = 12; @@ -28,16 +28,16 @@ int main (int argc, char *argv[]) { v1 = i + v0; /* { dg-error "conversion of scalar to vector" } */ v1 = 99999 + v0; /* { dg-error "conversion of scalar to vector" } */ f1 = d + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = 1.3 + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = sll + f0; /* { dg-error "conversion of scalar to vector" } */ f1 = ((int)998769576) + f0; /* { dg-error "conversion of scalar to vector" } */ /* convert.c should take care of this. */ - i1 = sfl + i0; /* { dg-error "can't convert value to a vector" } */ - i1 = 1.5 + i0; /* { dg-error "can't convert value to a vector" } */ - v1 = d + v0; /* { dg-error "can't convert value to a vector" } */ + i1 = sfl + i0; /* { dg-error "can't convert value to a vector|invalid operands" } */ + i1 = 1.5 + i0; /* { dg-error "can't convert value to a vector|invalid operands" } */ + v1 = d + v0; /* { dg-error "can't convert value to a vector|invalid operands" } */ return 0; } Index: testsuite/c-c++-common/vector-scalar.c =================================================================== --- testsuite/c-c++-common/vector-scalar.c (revision 0) +++ testsuite/c-c++-common/vector-scalar.c (revision 0) @@ -0,0 +1,10 @@ +/* { dg-do compile } */ + +typedef float vecf __attribute__ ((vector_size (4 * sizeof (float)))); +typedef short veci __attribute__ ((vector_size (8 * sizeof (short)))); + +void f (vecf *d, veci *i) +{ + (void) ((*d *= 2) < 0); + (void) ((((*i - 1) >> 2) != 0) | *i); +} Property changes on: testsuite/c-c++-common/vector-scalar.c ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision URL Added: svn:eol-style + native Index: c/c-typeck.c =================================================================== --- c/c-typeck.c (revision 191613) +++ c/c-typeck.c (working copy) @@ -33,38 +33,31 @@ along with GCC; see the file COPYING3. #include "langhooks.h" #include "c-tree.h" #include "c-lang.h" #include "flags.h" #include "intl.h" #include "target.h" #include "tree-iterator.h" #include "bitmap.h" #include "gimple.h" #include "c-family/c-objc.h" +#include "c-family/c-common.h" /* Possible cases of implicit bad conversions. Used to select diagnostic messages in convert_for_assignment. */ enum impl_conv { ic_argpass, ic_assign, ic_init, ic_return }; -/* Possibe cases of scalar_to_vector conversion. */ -enum stv_conv { - stv_error, /* Error occured. */ - stv_nothing, /* Nothing happened. */ - stv_firstarg, /* First argument must be expanded. */ - stv_secondarg /* Second argument must be expanded. */ -}; - /* The level of nesting inside "__alignof__". */ int in_alignof; /* The level of nesting inside "sizeof". */ int in_sizeof; /* The level of nesting inside "typeof". */ int in_typeof; /* The argument of last parsed sizeof expression, only to be tested @@ -9368,102 +9361,20 @@ push_cleanup (tree decl, tree cleanup, b bool stmt_expr; code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR; stmt = build_stmt (DECL_SOURCE_LOCATION (decl), code, NULL, cleanup); add_stmt (stmt); stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list); list = push_stmt_list (); TREE_OPERAND (stmt, 0) = list; STATEMENT_LIST_STMT_EXPR (list) = stmt_expr; } - -/* Convert scalar to vector for the range of operations. */ -static enum stv_conv -scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1) -{ - tree type0 = TREE_TYPE (op0); - tree type1 = TREE_TYPE (op1); - bool integer_only_op = false; - enum stv_conv ret = stv_firstarg; - - gcc_assert (TREE_CODE (type0) == VECTOR_TYPE - || TREE_CODE (type1) == VECTOR_TYPE); - switch (code) - { - case RSHIFT_EXPR: - case LSHIFT_EXPR: - if (TREE_CODE (type0) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) - { - if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) - { - error_at (loc, "conversion of scalar to vector " - "involves truncation"); - return stv_error; - } - else - return stv_firstarg; - } - break; - - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case BIT_AND_EXPR: - integer_only_op = true; - /* ... fall through ... */ - - case PLUS_EXPR: - case MINUS_EXPR: - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case TRUNC_MOD_EXPR: - case RDIV_EXPR: - if (TREE_CODE (type0) == VECTOR_TYPE) - { - tree tmp; - ret = stv_secondarg; - /* Swap TYPE0 with TYPE1 and OP0 with OP1 */ - tmp = type0; type0 = type1; type1 = tmp; - tmp = op0; op0 = op1; op1 = tmp; - } - - if (TREE_CODE (type0) == INTEGER_TYPE - && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) - { - if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) - { - error_at (loc, "conversion of scalar to vector " - "involves truncation"); - return stv_error; - } - return ret; - } - else if (!integer_only_op - /* Allow integer --> real conversion if safe. */ - && (TREE_CODE (type0) == REAL_TYPE - || TREE_CODE (type0) == INTEGER_TYPE) - && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1))) - { - if (unsafe_conversion_p (TREE_TYPE (type1), op0, false)) - { - error_at (loc, "conversion of scalar to vector " - "involves truncation"); - return stv_error; - } - return ret; - } - default: - break; - } - - return stv_nothing; -} /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. LOCATION is the operator's location. This function differs from `build' in several ways: the data type of the result is computed and recorded in it, warnings are generated if arg data types are invalid, special handling for addition and subtraction of pointers is known, and some optimization is done (operations on narrow ints are done in the narrower type when that gives the same result). Index: c/Make-lang.in =================================================================== --- c/Make-lang.in (revision 191613) +++ c/Make-lang.in (working copy) @@ -185,12 +185,12 @@ c/c-objc-common.o : c/c-objc-common.c c/ c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \ $(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \ gt-c-c-parser.h langhooks.h \ $(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \ c-family/c-objc.h c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h \ langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \ - c-family/c-objc.h + c-family/c-objc.h c-family/c-common.h Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 191613) +++ cp/typeck.c (working copy) @@ -3855,20 +3855,53 @@ cp_build_binary_op (location_t location, || (!null_ptr_cst_p (orig_op1) && !TYPE_PTR_OR_PTRMEM_P (type1))) && (complain & tf_warning)) { source_location loc = expansion_point_location_if_in_system_header (input_location); warning_at (loc, OPT_Wpointer_arith, "NULL used in arithmetic"); } + /* In case when one of the operands of the binary operation is + a vector and another is a scalar -- convert scalar to vector. */ + if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE)) + { + enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1); + + switch (convert_flag) + { + case stv_error: + return error_mark_node; + case stv_firstarg: + { + op0 = convert (TREE_TYPE (type1), op0); + op0 = build_vector_from_val (type1, op0); + type0 = TREE_TYPE (op0); + code0 = TREE_CODE (type0); + converted = 1; + break; + } + case stv_secondarg: + { + op1 = convert (TREE_TYPE (type0), op1); + op1 = build_vector_from_val (type0, op1); + type1 = TREE_TYPE (op1); + code1 = TREE_CODE (type1); + converted = 1; + break; + } + default: + break; + } + } + switch (code) { case MINUS_EXPR: /* Subtraction of two similar pointers. We must subtract them as integers, then divide by object size. */ if (code0 == POINTER_TYPE && code1 == POINTER_TYPE && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), TREE_TYPE (type1))) return pointer_diff (op0, op1, common_pointer_type (type0, type1), complain); @@ -3978,21 +4011,27 @@ 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 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) + { + result_type = type0; + converted = 1; + } + else 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; @@ -4015,21 +4054,27 @@ 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 == VECTOR_TYPE && code1 == VECTOR_TYPE + if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) + { + result_type = type0; + converted = 1; + } + else 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; Index: fold-const.c =================================================================== --- fold-const.c (revision 191613) +++ fold-const.c (working copy) @@ -12886,21 +12886,21 @@ fold_binary_loc (location_t loc, if (TREE_INT_CST_HIGH (arg01) == 0 && TREE_INT_CST_LOW (arg01) == (unsigned HOST_WIDE_INT) (TYPE_PRECISION (itype) - 1)) { if (TYPE_UNSIGNED (itype)) { itype = signed_type_for (itype); arg00 = fold_convert_loc (loc, itype, arg00); } return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR, - type, arg00, build_int_cst (itype, 0)); + type, arg00, build_zero_cst (itype)); } } /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y. */ if (integer_zerop (arg1) && TREE_CODE (arg0) == BIT_XOR_EXPR) return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)); /* (X ^ Y) == Y becomes X == 0. We know that Y has no side-effects. */