From patchwork Tue May 14 11:47:23 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 243684 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 2B3752C00A8 for ; Tue, 14 May 2013 21:47:36 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:in-reply-to:message-id:references :mime-version:content-type; q=dns; s=default; b=etfULmAQC8rkR2Qz MzJ9/95s+AzoOz9yLnWr2saS92T8HTEcuZL/OHryS+aWmtgNgOzSM2cI3bcrVavn bLFbkhfmtFaMVKZHb0ijorpJtjE9A3OMXMd2L8IlPYU1nwDDjLaD87d1t8+polPf oZUTKBaKsfnJ5ntrR2dwcSvnl18= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:in-reply-to:message-id:references :mime-version:content-type; s=default; bh=GEipyY9Ym+Lpl94C0yNLrg TVGrE=; b=Zui424fIjX73bghD/T+mwQrgRpkfdwgTBxtmuUx8Hb0Ef7gAIp/sM6 VRngCd9GcELq15xadC8VkFHYKZoGDT2t6x6PbG2DEtBmaa27zN6DylwbY5tdYk/f VYJO4HTBmL/Eb5Qx5DLN5W+QS6lm1M/FkMwF+4SQDWcdY6dVFXVmw= Received: (qmail 431 invoked by alias); 14 May 2013 11:47:29 -0000 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 Received: (qmail 415 invoked by uid 89); 14 May 2013 11:47:28 -0000 X-Spam-SWARE-Status: No, score=-5.9 required=5.0 tests=AWL, BAYES_00, KHOP_THREADED, RP_MATCHES_RCVD autolearn=ham version=3.3.1 Received: from mail3-relais-sop.national.inria.fr (HELO mail3-relais-sop.national.inria.fr) (192.134.164.104) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Tue, 14 May 2013 11:47:26 +0000 Received: from stedding.saclay.inria.fr ([193.55.250.194]) by mail3-relais-sop.national.inria.fr with ESMTP/TLS/DHE-RSA-AES128-SHA; 14 May 2013 13:47:23 +0200 Received: from glisse (helo=localhost) by stedding.saclay.inria.fr with local-esmtp (Exim 4.80) (envelope-from ) id 1UcDhT-0001qL-BK; Tue, 14 May 2013 13:47:23 +0200 Date: Tue, 14 May 2013 13:47:23 +0200 (CEST) From: Marc Glisse To: Richard Biener cc: gcc-patches@gcc.gnu.org Subject: Re: More vector folding In-Reply-To: Message-ID: References: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 X-Virus-Found: No On Tue, 14 May 2013, Richard Biener wrote: > On Mon, May 13, 2013 at 1:40 PM, Marc Glisse wrote: >> On Mon, 13 May 2013, Richard Biener wrote: >> >>> On Sat, May 11, 2013 at 11:38 AM, Marc Glisse >>> wrote: >>>> @@ -8274,28 +8269,34 @@ fold_unary_loc (location_t loc, enum tre >>>> { >>>> elem = VECTOR_CST_ELT (arg0, i); >>>> elem = fold_unary_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type), >>>> elem); >>>> if (elem == NULL_TREE) >>>> break; >>>> elements[i] = elem; >>>> } >>>> if (i == count) >>>> return build_vector (type, elements); >>>> } >>>> + else if (COMPARISON_CLASS_P (arg0) && VECTOR_INTEGER_TYPE_P >>>> (type)) >>>> + { >>>> + tree op_type = TREE_TYPE (TREE_OPERAND (arg0, 0)); >>>> + enum tree_code subcode = invert_tree_comparison (TREE_CODE >>>> (arg0), >>>> + HONOR_NANS (TYPE_MODE (op_type))); >>>> + if (subcode != ERROR_MARK) >>>> + return build2_loc (loc, subcode, type, TREE_OPERAND (arg0, >>>> 0), >>>> + TREE_OPERAND (arg0, 1)); >>>> + } >>>> + >>> >>> >>> I wonder why you restrict this to VECTOR_INTEGER_TYPE_P - for >>> TYPE_PRECISION == 1 type this should work, too. >> >> >> If TYPE_PRECISION == 1, wouldn't it be better to turn BIT_NOT_EXPR into >> TRUTH_NOT_EXPR? Then it will be handled by fold_truth_not_expr. > > Hmm, not sure - on GIMPLE we are no longer having the TRUTH_* tree > codes, so we don't want to fold BIT_* to TRUTH_*. ! I had never noticed that... >>> Also there should >>> never be a comparison resulting in a non-integer vector type, no? >> >> >> Yes, I was going to write VECTOR_TYPE_P, and adding integer seemed more >> explicit, but I can go back. > > Works for me. > >>>> return NULL_TREE; >>>> >>>> case TRUTH_NOT_EXPR: >>>> - /* The argument to invert_truthvalue must have Boolean type. */ >>>> - if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE) >>>> - arg0 = fold_convert_loc (loc, boolean_type_node, arg0); >>>> - >>>> /* Note that the operand of this must be an int >>>> and its values must be 0 or 1. >>>> ("true" is a fixed value perhaps depending on the language, >>>> but we don't handle values other than 1 correctly yet.) */ >>>> tem = fold_truth_not_expr (loc, arg0); >>>> if (!tem) >>>> return NULL_TREE; >>>> return fold_convert_loc (loc, type, tem); >>>> >>>> case REALPART_EXPR: >>>> @@ -9579,21 +9580,21 @@ fold_comparison (location_t loc, enum tr >>>> { >>>> tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0)); >>>> return fold_build2_loc (loc, code, type, >>>> fold_convert_loc (loc, cmp_type, >>>> TREE_OPERAND (arg1, 0)), >>>> TREE_OPERAND (arg0, 0)); >>>> } >>>> >>>> /* Fold ~X op C as X op' ~C, where op' is the swapped comparison. */ >>>> if (TREE_CODE (arg0) == BIT_NOT_EXPR >>>> - && TREE_CODE (arg1) == INTEGER_CST) >>>> + && (TREE_CODE (arg1) == INTEGER_CST || TREE_CODE (arg1) == >>>> VECTOR_CST)) >>>> { >>>> tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0)); >>>> return fold_build2_loc (loc, swap_tree_comparison (code), type, >>>> TREE_OPERAND (arg0, 0), >>>> fold_build1_loc (loc, BIT_NOT_EXPR, cmp_type, >>>> fold_convert_loc (loc, cmp_type, >>>> arg1))); >>>> } >>>> >>>> return NULL_TREE; >>>> } >>>> @@ -14030,61 +14031,67 @@ fold_ternary_loc (location_t loc, enum t >>>> return tem; >>>> } >>>> >>>> if (COMPARISON_CLASS_P (arg0) >>>> && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), >>>> op2, >>>> TREE_OPERAND (arg0, 1)) >>>> && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2)))) >>>> { >>>> location_t loc0 = expr_location_or (arg0, loc); >>>> - tem = fold_truth_not_expr (loc0, arg0); >>>> + tem = fold_unary_loc (loc0, VECTOR_TYPE_P (type) >>>> + ? BIT_NOT_EXPR >>>> + : TRUTH_NOT_EXPR, >>>> + TREE_TYPE (arg0), arg0); >>> >>> >>> since you don't restrict it here either .... >>> >>>> if (tem && COMPARISON_CLASS_P (tem)) >>>> { >>>> tem = fold_cond_expr_with_comparison (loc, type, tem, op2, >>>> op1); >>>> if (tem) >>>> return tem; >>>> } >>>> } >>>> >>>> - /* ??? Fixup the code below for VEC_COND_EXPR. */ >>>> - if (code == VEC_COND_EXPR) >>>> - return NULL_TREE; >>>> - >>>> /* 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)) >>>> && tree_swap_operands_p (op1, op2, false)) >>>> { >>>> location_t loc0 = expr_location_or (arg0, loc); >>>> /* See if this can be inverted. If it can't, possibly because >>>> it was a floating-point inequality comparison, don't do >>>> anything. */ >>>> - tem = fold_truth_not_expr (loc0, arg0); >>>> + tem = fold_unary_loc (loc0, VECTOR_TYPE_P (type) >>>> + ? BIT_NOT_EXPR >>>> + : TRUTH_NOT_EXPR, >>>> + TREE_TYPE (arg0), arg0); >>> >>> >>> Btw, splitting this out to a helper would be nice. >> >> >> Called fold_truth_not_expr? Oups ;-) >> fold_truth_invert? fold_invert_truth? > > Well, fold_invert_truthvalue maybe? Inverting a truthvalue is well-defined > for vectors and non-vectors and is more appropriate spelling for GIMPLE > where we don't have any TRUTH_NOT_EXPR anymore. Here is what I tested during the night, I'll just rename the function. I took the chance to remove an unnecessary alternative in TRUTH_XOR_EXPR. Passes bootstrap+testsuite on x86_64-linux-gnu. 2013-05-14 Marc Glisse gcc/ * fold-const.c (fold_negate_expr): Handle vectors. (fold_truth_not_expr): Make it static. (fold_invert_truth): New static function. (invert_truthvalue_loc): Handle vectors. Do not call fold_truth_not_expr directly. (fold_unary_loc) : Handle comparisons. : Do not cast to boolean. (fold_comparison): Handle vector constants. (fold_binary_loc) : Remove redundant code. (fold_ternary_loc) : Adapt more COND_EXPR optimizations. * tree.h (fold_truth_not_expr): Remove declaration. gcc/testsuite/ * g++.dg/ext/vector22.C: New testcase. * gcc.dg/binop-xor3.c: Remove xfail. Index: fold-const.c =================================================================== --- fold-const.c (revision 198853) +++ fold-const.c (working copy) @@ -519,21 +519,21 @@ fold_negate_expr (location_t loc, tree t { tree type = TREE_TYPE (t); tree tem; switch (TREE_CODE (t)) { /* Convert - (~A) to A + 1. */ case BIT_NOT_EXPR: if (INTEGRAL_TYPE_P (type)) return fold_build2_loc (loc, PLUS_EXPR, type, TREE_OPERAND (t, 0), - build_int_cst (type, 1)); + build_one_cst (type)); break; case INTEGER_CST: tem = fold_negate_const (t, type); if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t) || !TYPE_OVERFLOW_TRAPS (type)) return tem; break; case REAL_CST: @@ -3078,21 +3078,21 @@ omit_two_operands_loc (location_t loc, t } /* Return a simplified tree node for the truth-negation of ARG. This never alters ARG itself. We assume that ARG is an operation that returns a truth value (0 or 1). FIXME: one would think we would fold the result, but it causes problems with the dominator optimizer. */ -tree +static tree fold_truth_not_expr (location_t loc, tree arg) { tree type = TREE_TYPE (arg); enum tree_code code = TREE_CODE (arg); location_t loc1, loc2; /* If this is a comparison, we can simply invert it, except for floating-point non-equality comparisons, in which case we just enclose a TRUTH_NOT_EXPR around what we have. */ @@ -3213,40 +3213,50 @@ fold_truth_not_expr (location_t loc, tre case CLEANUP_POINT_EXPR: loc1 = expr_location_or (TREE_OPERAND (arg, 0), loc); return build1_loc (loc, CLEANUP_POINT_EXPR, type, invert_truthvalue_loc (loc1, TREE_OPERAND (arg, 0))); default: return NULL_TREE; } } +/* Fold the truth-negation of ARG. This never alters ARG itself. We + assume that ARG is an operation that returns a truth value (0 or 1 + for scalars, 0 or -1 for vectors). Return the folded expression if + folding is successful. Otherwise, return NULL_TREE. */ + +static tree +fold_invert_truth (location_t loc, tree arg) +{ + tree type = TREE_TYPE (arg); + return fold_unary_loc (loc, VECTOR_TYPE_P (type) + ? BIT_NOT_EXPR + : TRUTH_NOT_EXPR, + type, arg); +} + /* Return a simplified tree node for the truth-negation of ARG. This never alters ARG itself. We assume that ARG is an operation that - returns a truth value (0 or 1). - - FIXME: one would think we would fold the result, but it causes - problems with the dominator optimizer. */ + returns a truth value (0 or 1 for scalars, 0 or -1 for vectors). */ tree invert_truthvalue_loc (location_t loc, tree arg) { - tree tem; - if (TREE_CODE (arg) == ERROR_MARK) return arg; - tem = fold_truth_not_expr (loc, arg); - if (!tem) - tem = build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg), arg); - - return tem; + tree type = TREE_TYPE (arg); + return fold_build1_loc (loc, VECTOR_TYPE_P (type) + ? BIT_NOT_EXPR + : TRUTH_NOT_EXPR, + type, arg); } /* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both operands are another bit-wise operation with a common input. If so, distribute the bit operations to save an operation and possibly two if constants are involved. For example, convert (A | B) & (A | C) into A | (B & C) Further simplification will occur if B and C are constants. If this optimization cannot be done, 0 will be returned. */ @@ -8274,28 +8284,36 @@ fold_unary_loc (location_t loc, enum tre { elem = VECTOR_CST_ELT (arg0, i); elem = fold_unary_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type), elem); if (elem == NULL_TREE) break; elements[i] = elem; } if (i == count) return build_vector (type, elements); } + else if (COMPARISON_CLASS_P (arg0) + && (VECTOR_TYPE_P (type) + || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1))) + { + tree op_type = TREE_TYPE (TREE_OPERAND (arg0, 0)); + enum tree_code subcode = invert_tree_comparison (TREE_CODE (arg0), + HONOR_NANS (TYPE_MODE (op_type))); + if (subcode != ERROR_MARK) + return build2_loc (loc, subcode, type, TREE_OPERAND (arg0, 0), + TREE_OPERAND (arg0, 1)); + } + return NULL_TREE; case TRUTH_NOT_EXPR: - /* The argument to invert_truthvalue must have Boolean type. */ - if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE) - arg0 = fold_convert_loc (loc, boolean_type_node, arg0); - /* Note that the operand of this must be an int and its values must be 0 or 1. ("true" is a fixed value perhaps depending on the language, but we don't handle values other than 1 correctly yet.) */ tem = fold_truth_not_expr (loc, arg0); if (!tem) return NULL_TREE; return fold_convert_loc (loc, type, tem); case REALPART_EXPR: @@ -9579,21 +9597,21 @@ fold_comparison (location_t loc, enum tr { tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0)); return fold_build2_loc (loc, code, type, fold_convert_loc (loc, cmp_type, TREE_OPERAND (arg1, 0)), TREE_OPERAND (arg0, 0)); } /* Fold ~X op C as X op' ~C, where op' is the swapped comparison. */ if (TREE_CODE (arg0) == BIT_NOT_EXPR - && TREE_CODE (arg1) == INTEGER_CST) + && (TREE_CODE (arg1) == INTEGER_CST || TREE_CODE (arg1) == VECTOR_CST)) { tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0)); return fold_build2_loc (loc, swap_tree_comparison (code), type, TREE_OPERAND (arg0, 0), fold_build1_loc (loc, BIT_NOT_EXPR, cmp_type, fold_convert_loc (loc, cmp_type, arg1))); } return NULL_TREE; } @@ -12671,25 +12689,21 @@ fold_binary_loc (location_t loc, return NULL_TREE; case TRUTH_XOR_EXPR: /* If the second arg is constant zero, drop it. */ if (integer_zerop (arg1)) return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0)); /* If the second arg is constant true, this is a logical inversion. */ if (integer_onep (arg1)) { - /* Only call invert_truthvalue if operand is a truth value. */ - if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE) - tem = fold_build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg0), arg0); - else - tem = invert_truthvalue_loc (loc, arg0); + tem = invert_truthvalue_loc (loc, arg0); return non_lvalue_loc (loc, fold_convert_loc (loc, type, tem)); } /* Identical arguments cancel to zero. */ if (operand_equal_p (arg0, arg1, 0)) return omit_one_operand_loc (loc, type, integer_zero_node, arg0); /* !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); @@ -14036,61 +14050,61 @@ fold_ternary_loc (location_t loc, enum t return tem; } if (COMPARISON_CLASS_P (arg0) && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), op2, TREE_OPERAND (arg0, 1)) && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2)))) { location_t loc0 = expr_location_or (arg0, loc); - tem = fold_truth_not_expr (loc0, arg0); + tem = fold_invert_truth (loc0, arg0); if (tem && COMPARISON_CLASS_P (tem)) { tem = fold_cond_expr_with_comparison (loc, type, tem, op2, op1); if (tem) return tem; } } - /* ??? Fixup the code below for VEC_COND_EXPR. */ - if (code == VEC_COND_EXPR) - return NULL_TREE; - /* 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)) && tree_swap_operands_p (op1, op2, false)) { location_t loc0 = expr_location_or (arg0, loc); /* See if this can be inverted. If it can't, possibly because it was a floating-point inequality comparison, don't do anything. */ - tem = fold_truth_not_expr (loc0, arg0); + tem = fold_invert_truth (loc0, arg0); if (tem) return fold_build3_loc (loc, code, type, tem, op2, op1); } /* Convert A ? 1 : 0 to simply A. */ - if (integer_onep (op1) + if ((code == VEC_COND_EXPR ? integer_all_onesp (op1) + : (integer_onep (op1) + && !VECTOR_TYPE_P (type))) && integer_zerop (op2) /* If we try to convert OP0 to our type, the call to fold will try to move the conversion inside a COND, which will recurse. In that case, the COND_EXPR is probably the best choice, so leave it alone. */ && type == TREE_TYPE (arg0)) return pedantic_non_lvalue_loc (loc, arg0); /* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR over COND_EXPR in cases such as floating point comparisons. */ if (integer_zerop (op1) - && integer_onep (op2) + && (code == VEC_COND_EXPR ? integer_all_onesp (op2) + : (integer_onep (op2) + && !VECTOR_TYPE_P (type))) && truth_value_p (TREE_CODE (arg0))) return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, invert_truthvalue_loc (loc, arg0))); /* A < 0 ? : 0 is simply (A & ). */ if (TREE_CODE (arg0) == LT_EXPR && integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (op2) @@ -14193,60 +14207,67 @@ fold_ternary_loc (location_t loc, enum t && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1), arg1, OEP_ONLY_CONST)) return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0))); /* Convert A ? B : 0 into A && B if A and B are truth values. */ if (integer_zerop (op2) && truth_value_p (TREE_CODE (arg0)) - && truth_value_p (TREE_CODE (arg1))) - return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type, - fold_convert_loc (loc, type, arg0), - arg1); + && truth_value_p (TREE_CODE (arg1)) + && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type))) + return fold_build2_loc (loc, code == VEC_COND_EXPR ? BIT_AND_EXPR + : TRUTH_ANDIF_EXPR, + type, fold_convert_loc (loc, type, arg0), arg1); /* Convert A ? B : 1 into !A || B if A and B are truth values. */ - if (integer_onep (op2) + if (code == VEC_COND_EXPR ? integer_all_onesp (op2) : integer_onep (op2) && truth_value_p (TREE_CODE (arg0)) - && truth_value_p (TREE_CODE (arg1))) + && truth_value_p (TREE_CODE (arg1)) + && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type))) { location_t loc0 = expr_location_or (arg0, loc); /* Only perform transformation if ARG0 is easily inverted. */ - tem = fold_truth_not_expr (loc0, arg0); + tem = fold_invert_truth (loc0, arg0); if (tem) - return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type, - fold_convert_loc (loc, type, tem), - arg1); + return fold_build2_loc (loc, code == VEC_COND_EXPR + ? BIT_IOR_EXPR + : TRUTH_ORIF_EXPR, + type, fold_convert_loc (loc, type, tem), + arg1); } /* Convert A ? 0 : B into !A && B if A and B are truth values. */ if (integer_zerop (arg1) && truth_value_p (TREE_CODE (arg0)) - && truth_value_p (TREE_CODE (op2))) + && truth_value_p (TREE_CODE (op2)) + && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type))) { location_t loc0 = expr_location_or (arg0, loc); /* Only perform transformation if ARG0 is easily inverted. */ - tem = fold_truth_not_expr (loc0, arg0); + tem = fold_invert_truth (loc0, arg0); if (tem) - return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type, - fold_convert_loc (loc, type, tem), - op2); + return fold_build2_loc (loc, code == VEC_COND_EXPR + ? BIT_AND_EXPR : TRUTH_ANDIF_EXPR, + type, fold_convert_loc (loc, type, tem), + op2); } /* Convert A ? 1 : B into A || B if A and B are truth values. */ - if (integer_onep (arg1) + if (code == VEC_COND_EXPR ? integer_all_onesp (arg1) : integer_onep (arg1) && truth_value_p (TREE_CODE (arg0)) - && truth_value_p (TREE_CODE (op2))) - return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type, - fold_convert_loc (loc, type, arg0), - op2); + && truth_value_p (TREE_CODE (op2)) + && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type))) + return fold_build2_loc (loc, code == VEC_COND_EXPR + ? BIT_IOR_EXPR : TRUTH_ORIF_EXPR, + type, fold_convert_loc (loc, type, arg0), op2); return NULL_TREE; case CALL_EXPR: /* CALL_EXPRs used to be ternary exprs. Catch any mistaken uses of fold_ternary on them. */ gcc_unreachable (); case BIT_FIELD_REF: if ((TREE_CODE (arg0) == VECTOR_CST Index: testsuite/gcc.dg/binop-xor3.c =================================================================== --- testsuite/gcc.dg/binop-xor3.c (revision 198853) +++ testsuite/gcc.dg/binop-xor3.c (working copy) @@ -1,11 +1,11 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ int foo (int a, int b) { return ((a && !b) || (!a && b)); } -/* { dg-final { scan-tree-dump-times "\\\^" 1 "optimized" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "\\\^" 1 "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ Index: testsuite/g++.dg/ext/vector22.C =================================================================== --- testsuite/g++.dg/ext/vector22.C (revision 0) +++ testsuite/g++.dg/ext/vector22.C (revision 0) @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-gimple" } */ + +typedef unsigned vec __attribute__((vector_size(4*sizeof(int)))); + +void f(vec*a,vec*b){ + *a=(*a)?-1:(*b<10); + *b=(*b)?(*a<10):0; +} +void g(vec*a,vec*b){ + *a=(*a)?(*a<*a):-1; + *b=(*b)?-1:(*b<*b); +} +void h(vec*a){ + *a=(~*a==5); +} + +/* { dg-final { scan-tree-dump-not "~" "gimple" } } */ +/* { dg-final { scan-tree-dump-not "VEC_COND_EXPR" "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ Property changes on: testsuite/g++.dg/ext/vector22.C ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision URL Added: svn:eol-style + native Index: tree.h =================================================================== --- tree.h (revision 198853) +++ tree.h (working copy) @@ -5763,21 +5763,20 @@ extern int operand_equal_p (const_tree, extern int multiple_of_p (tree, const_tree, const_tree); #define omit_one_operand(T1,T2,T3)\ omit_one_operand_loc (UNKNOWN_LOCATION, T1, T2, T3) extern tree omit_one_operand_loc (location_t, tree, tree, tree); #define omit_two_operands(T1,T2,T3,T4)\ omit_two_operands_loc (UNKNOWN_LOCATION, T1, T2, T3, T4) extern tree omit_two_operands_loc (location_t, tree, tree, tree, tree); #define invert_truthvalue(T)\ invert_truthvalue_loc(UNKNOWN_LOCATION, T) extern tree invert_truthvalue_loc (location_t, tree); -extern tree fold_truth_not_expr (location_t, tree); extern tree fold_unary_to_constant (enum tree_code, tree, tree); extern tree fold_binary_to_constant (enum tree_code, tree, tree, tree); extern tree fold_read_from_constant_string (tree); extern tree int_const_binop (enum tree_code, const_tree, const_tree); #define build_fold_addr_expr(T)\ build_fold_addr_expr_loc (UNKNOWN_LOCATION, (T)) extern tree build_fold_addr_expr_loc (location_t, tree); #define build_fold_addr_expr_with_type(T,TYPE)\ build_fold_addr_expr_with_type_loc (UNKNOWN_LOCATION, (T), TYPE) extern tree build_fold_addr_expr_with_type_loc (location_t, tree, tree);