From patchwork Sun May 24 08:33:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 475949 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.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 5DD4414027F for ; Sun, 24 May 2015 18:34:14 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=T34xbZnS; dkim-atps=neutral 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:subject:message-id:mime-version:content-type :content-id; q=dns; s=default; b=xlxzvZzpimtZCv+AvDPaOV9O4jOEByK yrSrGm4Wpwx+K44Q676mkxs2nAGnuqyGOr8wgCEdiZsFGM2HpoMfP7DcZdr2035B irR9mhlpLb7CqR0JgjzTN26sXt9humgzu5stSmOK2VzNVt8wb4OAdmnqxQJ8QJHJ OMTCmqEmOvQI= 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:subject:message-id:mime-version:content-type :content-id; s=default; bh=6Siva3LkY7Y/AMXhPS39O0+C9xc=; b=T34xb ZnSV+zk/3Nvv5eyglDCLIW+kF9ODluzgNj66jz4kxO7VyBFmedIy3qQm2fR0uGAX 7dG8sy8S+UzVA89POpL6BzPHVW93YUj28QB+P1wBz9Xuwrix833ypOmCDn+x0WSX B7+JBKsAGh28JYh1IIW0NspU8qq8XqmdN6C3AQ= Received: (qmail 86546 invoked by alias); 24 May 2015 08:34:05 -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 86533 invoked by uid 89); 24 May 2015 08:34:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.6 required=5.0 tests=AWL, BAYES_50, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mail3-relais-sop.national.inria.fr Received: from mail3-relais-sop.national.inria.fr (HELO mail3-relais-sop.national.inria.fr) (192.134.164.104) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Sun, 24 May 2015 08:33:53 +0000 Received: from stedding.saclay.inria.fr (HELO stedding) ([193.55.250.194]) by mail3-relais-sop.national.inria.fr with ESMTP/TLS/AES128-SHA; 24 May 2015 10:33:49 +0200 Received: from glisse (helo=localhost) by stedding with local-esmtp (Exim 4.85) (envelope-from ) id 1YwRLx-0003N4-8U for gcc-patches@gcc.gnu.org; Sun, 24 May 2015 10:33:49 +0200 Date: Sun, 24 May 2015 10:33:49 +0200 (CEST) From: Marc Glisse To: gcc-patches@gcc.gnu.org Subject: Move ABS detection from fold-const.c to match.pd Message-ID: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Content-ID: Hello, I don't think this pattern is done in the branch. Here I am trying to match what is done in fold-const, but the idea is that we can later add an extra block where we replace (cmp (minus @2 @3) zerop) with (cmp @2 @3), maybe with some adjustments ("convert?" all over the place), to help with PR 64450 / PR 61734. I didn't exactly match the code in fold-const.c, among other things because I didn't feel like calling operand_equal_for_comparison_p, and strip_nops can translate to quite heavy patterns. Except for a few irrelevant cases (where I simplify more), this seems to generate the same .original dumps in the cases I tried. But I am not claiming this is the best way to arrange that code, better ideas are welcome. I don't understand the old code handling unsigned, but I couldn't find a case where the new code (doing nothing special for unsigned) generated a different .original dump. The last pattern had a strange mix of requiring integer_zerop and talking about signed zero and NaN, I didn't try to preserve that. The change to genmatch is for zerop, which doesn't try to valueize anything. I had a few issues with the machinery. First, genmatch was generating a switch with duplicate cases (miraculously, replacing 'cond' with an iteration on 'cnd' worked around it). Second, (plus @0 (negate@0 @1)) is treated as (plus @0 @0), the pattern on the second occurence of the capture is silently ignored. Regtested on ppc64le-redhat-linux. 2015-05-25 Marc Glisse * genmatch.c (write_predicate): Add ATTRIBUTE_UNUSED. * match.pd (A op 0 ? A : -A, A op 0 ? A : 0): New simplifications. * fold-const.c (fold_cond_expr_with_comparison): Remove corresponding code. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 223630) +++ gcc/fold-const.c (working copy) @@ -4875,112 +4875,25 @@ merge_ranges (int *pin_p, tree *plow, tr Return a folded expression whose code is not a COND_EXPR anymore, or NULL_TREE if no folding opportunity is found. */ static tree fold_cond_expr_with_comparison (location_t loc, tree type, tree arg0, tree arg1, tree arg2) { enum tree_code comp_code = TREE_CODE (arg0); tree arg00 = TREE_OPERAND (arg0, 0); tree arg01 = TREE_OPERAND (arg0, 1); - tree arg1_type = TREE_TYPE (arg1); tree tem; STRIP_NOPS (arg1); STRIP_NOPS (arg2); - /* If we have A op 0 ? A : -A, consider applying the following - transformations: - - A == 0? A : -A same as -A - A != 0? A : -A same as A - A >= 0? A : -A same as abs (A) - A > 0? A : -A same as abs (A) - A <= 0? A : -A same as -abs (A) - A < 0? A : -A same as -abs (A) - - None of these transformations work for modes with signed - zeros. If A is +/-0, the first two transformations will - change the sign of the result (from +0 to -0, or vice - versa). The last four will fix the sign of the result, - even though the original expressions could be positive or - negative, depending on the sign of A. - - Note that all these transformations are correct if A is - NaN, since the two alternatives (A and -A) are also NaNs. */ - if (!HONOR_SIGNED_ZEROS (element_mode (type)) - && (FLOAT_TYPE_P (TREE_TYPE (arg01)) - ? real_zerop (arg01) - : integer_zerop (arg01)) - && ((TREE_CODE (arg2) == NEGATE_EXPR - && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0)) - /* In the case that A is of the form X-Y, '-A' (arg2) may - have already been folded to Y-X, check for that. */ - || (TREE_CODE (arg1) == MINUS_EXPR - && TREE_CODE (arg2) == MINUS_EXPR - && operand_equal_p (TREE_OPERAND (arg1, 0), - TREE_OPERAND (arg2, 1), 0) - && operand_equal_p (TREE_OPERAND (arg1, 1), - TREE_OPERAND (arg2, 0), 0)))) - switch (comp_code) - { - case EQ_EXPR: - case UNEQ_EXPR: - tem = fold_convert_loc (loc, arg1_type, arg1); - return pedantic_non_lvalue_loc (loc, - fold_convert_loc (loc, type, - negate_expr (tem))); - case NE_EXPR: - case LTGT_EXPR: - return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1)); - case UNGE_EXPR: - case UNGT_EXPR: - if (flag_trapping_math) - break; - /* Fall through. */ - case GE_EXPR: - case GT_EXPR: - if (TYPE_UNSIGNED (TREE_TYPE (arg1))) - arg1 = fold_convert_loc (loc, signed_type_for - (TREE_TYPE (arg1)), arg1); - tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1); - return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem)); - case UNLE_EXPR: - case UNLT_EXPR: - if (flag_trapping_math) - break; - case LE_EXPR: - case LT_EXPR: - if (TYPE_UNSIGNED (TREE_TYPE (arg1))) - arg1 = fold_convert_loc (loc, signed_type_for - (TREE_TYPE (arg1)), arg1); - tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1); - return negate_expr (fold_convert_loc (loc, type, tem)); - default: - gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison); - break; - } - - /* A != 0 ? A : 0 is simply A, unless A is -0. Likewise - A == 0 ? A : 0 is always 0 unless A is -0. Note that - both transformations are correct when A is NaN: A != 0 - is then true, and A == 0 is false. */ - - if (!HONOR_SIGNED_ZEROS (element_mode (type)) - && integer_zerop (arg01) && integer_zerop (arg2)) - { - if (comp_code == NE_EXPR) - return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1)); - else if (comp_code == EQ_EXPR) - return build_zero_cst (type); - } - /* Try some transformations of A op B ? A : B. A == B? A : B same as B A != B? A : B same as A A >= B? A : B same as max (A, B) A > B? A : B same as max (B, A) A <= B? A : B same as min (A, B) A < B? A : B same as min (B, A) As above, these transformations don't work in the presence Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (revision 223630) +++ gcc/genmatch.c (working copy) @@ -2657,21 +2657,21 @@ decision_tree::gen_generic (FILE *f) /* Output code to implement the predicate P from the decision tree DT. */ void write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple) { fprintf (f, "\nbool\n" "%s%s (tree t%s%s)\n" "{\n", gimple ? "gimple_" : "tree_", p->id, p->nargs > 0 ? ", tree *res_ops" : "", - gimple ? ", tree (*valueize)(tree)" : ""); + gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : ""); /* Conveniently make 'type' available. */ fprintf (f, "tree type = TREE_TYPE (t);\n"); if (!gimple) fprintf (f, "if (TREE_SIDE_EFFECTS (t)) return false;\n"); dt.root->gen_kids (f, gimple); fprintf (f, "return false;\n" "}\n"); } Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 223630) +++ gcc/match.pd (working copy) @@ -1131,10 +1131,106 @@ along with GCC; see the file COPYING3. && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)) || tree_int_cst_sgn (@4) >= 0) && single_use (@5)) (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))) (with { tree ntype = TREE_TYPE (@0); } (convert (bit_and (op @0 @1) (convert:ntype @4))))) (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); } (convert (bit_and (op (convert:utype @0) (convert:utype @1)) (convert:utype @4))))))) + +(match zerop integer_zerop) +(match zerop real_zerop) + +/* If we have A op 0 ? A : -A, consider applying the following + transformations: + + A == 0? A : -A same as -A + A != 0? A : -A same as A + A >= 0? A : -A same as abs (A) + A > 0? A : -A same as abs (A) + A <= 0? A : -A same as -abs (A) + A < 0? A : -A same as -abs (A) + + None of these transformations work for modes with signed + zeros. If A is +/-0, the first two transformations will + change the sign of the result (from +0 to -0, or vice + versa). The last four will fix the sign of the result, + even though the original expressions could be positive or + negative, depending on the sign of A. + + Note that all these transformations are correct if A is + NaN, since the two alternatives (A and -A) are also NaNs. */ +(if (!HONOR_SIGNED_ZEROS (type)) + (for cnd (cond vec_cond) + (for cmp (tcc_comparison) + (simplify + (cnd (cmp @0 zerop) (convert?@2 @0) (negate@1 @2)) + (if (cmp == EQ_EXPR || cmp == UNEQ_EXPR) + @1) + (if (cmp == NE_EXPR || cmp == LTGT_EXPR) + (non_lvalue @2)) + (if (TYPE_SIGN (TREE_TYPE (@0)) == SIGNED /* implicit */ + && TYPE_SIGN (type) == SIGNED + && element_precision (type) >= element_precision (TREE_TYPE (@0))) + (if (cmp == GE_EXPR || cmp == GT_EXPR + || (!flag_trapping_math && (cmp == UNGE_EXPR || cmp == UNGT_EXPR))) + (abs @2)) + (if (cmp == LE_EXPR || cmp == LT_EXPR + || (!flag_trapping_math && (cmp == UNLE_EXPR || cmp == UNLT_EXPR))) + (negate (abs @2))))) + /* Now with the branches swapped. */ + (simplify + (cnd (cmp @0 zerop) (negate@1 (convert?@2 @0)) @2) + (if (cmp == EQ_EXPR || cmp == UNEQ_EXPR) + (non_lvalue @2)) + (if (cmp == NE_EXPR || cmp == LTGT_EXPR) + @1) + (if (TYPE_SIGN (TREE_TYPE (@0)) == SIGNED /* implicit */ + && TYPE_SIGN (type) == SIGNED + && element_precision (type) >= element_precision (TREE_TYPE (@0))) + (if (cmp == GE_EXPR || cmp == GT_EXPR + || (!flag_trapping_math && (cmp == UNGE_EXPR || cmp == UNGT_EXPR))) + (negate (abs @2))) + (if (cmp == LE_EXPR || cmp == LT_EXPR + || (!flag_trapping_math && (cmp == UNLE_EXPR || cmp == UNLT_EXPR))) + (abs @2)))) + + /* Same as above, but if A is X - Y, -A may be spelled Y - X. */ + (simplify + (cnd (cmp (minus@0 @2 @3) zerop) @0 (minus@1 @3 @2)) + (if (cmp == EQ_EXPR || cmp == UNEQ_EXPR) + @1) + (if (cmp == NE_EXPR || cmp == LTGT_EXPR) + @0) + (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type)) + (if (cmp == GE_EXPR || cmp == GT_EXPR + || (!flag_trapping_math && (cmp == UNGE_EXPR || cmp == UNGT_EXPR))) + (abs @0)) + (if (cmp == LE_EXPR || cmp == LT_EXPR + || (!flag_trapping_math && (cmp == UNLE_EXPR || cmp == UNLT_EXPR))) + (negate (abs @0))))) + (simplify + (cnd (cmp (minus@0 @2 @3) zerop) (minus@1 @3 @2) @0) + (if (cmp == EQ_EXPR || cmp == UNEQ_EXPR) + @0) + (if (cmp == NE_EXPR || cmp == LTGT_EXPR) + @1) + (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type)) + (if (cmp == GE_EXPR || cmp == GT_EXPR + || (!flag_trapping_math && (cmp == UNGE_EXPR || cmp == UNGT_EXPR))) + (negate (abs @0))) + (if (cmp == LE_EXPR || cmp == LT_EXPR + || (!flag_trapping_math && (cmp == UNLE_EXPR || cmp == UNLT_EXPR))) + (abs @0))))) + + /* A != 0 ? A : 0 is simply A, unless A is -0. Likewise + A == 0 ? A : 0 is always 0 unless A is -0. Note that + both transformations are correct when A is NaN: A != 0 + is then true, and A == 0 is false. */ + (simplify + (cnd (ne @0 zerop) (convert? @0) zerop) + (non_lvalue (convert @0))) + (simplify + (cnd (eq @0 zerop) (convert? @0) zerop@1) + (non_lvalue (convert @1)))))