From patchwork Sun Jun 12 08:30:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 634154 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 3rS8Ht6yMqz9sBM for ; Sun, 12 Jun 2016 18:30:49 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=fUj9JFYf; 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; q=dns; s= default; b=DMyUG8NeQiktj40FE2iogvFJuEzJO4x0fl43mLreWXIH1O1Sc02B/ ns0VPSaS29aFGju1MCHlid/yztAI63ew3OOY0hdT69WKE6IE5rN/R2L5kyM9YL0O O1LgOK2CMd7G0Uuy6JZW6GKpHLfuMuhPbA3OTJeaCmnGPLdrzM0ags= 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; s= default; bh=m32TiQRT1jjGpGloIL67TmbRuY0=; b=fUj9JFYfZf7Ffz7xg/sO TXmTV2sMi8V8ytTQS/hQKqLMmbxEt5yBmM+RHi98v0boOnJ38bgCpi+KUzoj6Zhv WEtOw5gttg1fuka9Z6XOTnFGeMBkY7FHp7u7XkH8HT1TlQop841naU/QLrkBU2fF awsSty2kIkxG138T3uqYYj0= Received: (qmail 109500 invoked by alias); 12 Jun 2016 08:30:37 -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 109479 invoked by uid 89); 12 Jun 2016 08:30:34 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=s3, multiplied, s2, D*0 X-HELO: mail2-relais-roc.national.inria.fr Received: from mail2-relais-roc.national.inria.fr (HELO mail2-relais-roc.national.inria.fr) (192.134.164.83) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sun, 12 Jun 2016 08:30:23 +0000 Received: from 81-65-27-132.rev.numericable.fr (HELO laptop-mg.local) ([81.65.27.132]) by mail2-relais-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-SHA; 12 Jun 2016 10:30:19 +0200 Date: Sun, 12 Jun 2016 10:30:14 +0200 (CEST) From: Marc Glisse To: gcc-patches@gcc.gnu.org Subject: Move optimize_minmax_comparison to match.pd Message-ID: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Hello, this move is pretty straightforward. The transformation would probably work just fine for any type (floats, vectors), but I didn't want the headache of checking the behavior for NaN. Bootstrap+regtest on powerpc64le-unknown-linux-gnu. 2016-06-13 Marc Glisse * fold-const.c (optimize_minmax_comparison): Remove. (fold_comparison): Remove call to the above. * match.pd (MIN (X, Y) == X, MIN (X, 5) == 0, MIN (X, C1) < C2): New transformations. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 237336) +++ gcc/fold-const.c (working copy) @@ -121,22 +121,20 @@ static tree eval_subst (location_t, tree static tree optimize_bit_field_compare (location_t, enum tree_code, tree, tree, tree); static int simple_operand_p (const_tree); static bool simple_operand_p_2 (tree); static tree range_binop (enum tree_code, tree, tree, int, tree, int); static tree range_predecessor (tree); static tree range_successor (tree); static tree fold_range_test (location_t, enum tree_code, tree, tree, tree); static tree fold_cond_expr_with_comparison (location_t, tree, tree, tree, tree); static tree unextend (tree, int, int, tree); -static tree optimize_minmax_comparison (location_t, enum tree_code, - tree, tree, tree); static tree extract_muldiv (tree, tree, enum tree_code, tree, bool *); static tree extract_muldiv_1 (tree, tree, enum tree_code, tree, bool *); static tree fold_binary_op_with_conditional_arg (location_t, enum tree_code, tree, tree, tree, tree, tree, int); static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree); static bool reorder_operands_p (const_tree, const_tree); static tree fold_negate_const (tree, tree); static tree fold_not_const (const_tree, tree); @@ -5972,124 +5970,20 @@ fold_truth_andor_1 (location_t loc, enum ll_unsignedp || rl_unsignedp, ll_reversep); ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask); if (! all_ones_mask_p (ll_mask, lnbitsize)) result = build2_loc (loc, BIT_AND_EXPR, lntype, result, ll_mask); return build2_loc (loc, wanted_code, truth_type, result, const_binop (BIT_IOR_EXPR, l_const, r_const)); } -/* Optimize T, which is a comparison of a MIN_EXPR or MAX_EXPR with a - constant. */ - -static tree -optimize_minmax_comparison (location_t loc, enum tree_code code, tree type, - tree op0, tree op1) -{ - tree arg0 = op0; - enum tree_code op_code; - tree comp_const; - tree minmax_const; - int consts_equal, consts_lt; - tree inner; - - STRIP_SIGN_NOPS (arg0); - - op_code = TREE_CODE (arg0); - minmax_const = TREE_OPERAND (arg0, 1); - comp_const = fold_convert_loc (loc, TREE_TYPE (arg0), op1); - consts_equal = tree_int_cst_equal (minmax_const, comp_const); - consts_lt = tree_int_cst_lt (minmax_const, comp_const); - inner = TREE_OPERAND (arg0, 0); - - /* If something does not permit us to optimize, return the original tree. */ - if ((op_code != MIN_EXPR && op_code != MAX_EXPR) - || TREE_CODE (comp_const) != INTEGER_CST - || TREE_OVERFLOW (comp_const) - || TREE_CODE (minmax_const) != INTEGER_CST - || TREE_OVERFLOW (minmax_const)) - return NULL_TREE; - - /* Now handle all the various comparison codes. We only handle EQ_EXPR - and GT_EXPR, doing the rest with recursive calls using logical - simplifications. */ - switch (code) - { - case NE_EXPR: case LT_EXPR: case LE_EXPR: - { - tree tem - = optimize_minmax_comparison (loc, - invert_tree_comparison (code, false), - type, op0, op1); - if (tem) - return invert_truthvalue_loc (loc, tem); - return NULL_TREE; - } - - case GE_EXPR: - return - fold_build2_loc (loc, TRUTH_ORIF_EXPR, type, - optimize_minmax_comparison - (loc, EQ_EXPR, type, arg0, comp_const), - optimize_minmax_comparison - (loc, GT_EXPR, type, arg0, comp_const)); - - case EQ_EXPR: - if (op_code == MAX_EXPR && consts_equal) - /* MAX (X, 0) == 0 -> X <= 0 */ - return fold_build2_loc (loc, LE_EXPR, type, inner, comp_const); - - else if (op_code == MAX_EXPR && consts_lt) - /* MAX (X, 0) == 5 -> X == 5 */ - return fold_build2_loc (loc, EQ_EXPR, type, inner, comp_const); - - else if (op_code == MAX_EXPR) - /* MAX (X, 0) == -1 -> false */ - return omit_one_operand_loc (loc, type, integer_zero_node, inner); - - else if (consts_equal) - /* MIN (X, 0) == 0 -> X >= 0 */ - return fold_build2_loc (loc, GE_EXPR, type, inner, comp_const); - - else if (consts_lt) - /* MIN (X, 0) == 5 -> false */ - return omit_one_operand_loc (loc, type, integer_zero_node, inner); - - else - /* MIN (X, 0) == -1 -> X == -1 */ - return fold_build2_loc (loc, EQ_EXPR, type, inner, comp_const); - - case GT_EXPR: - if (op_code == MAX_EXPR && (consts_equal || consts_lt)) - /* MAX (X, 0) > 0 -> X > 0 - MAX (X, 0) > 5 -> X > 5 */ - return fold_build2_loc (loc, GT_EXPR, type, inner, comp_const); - - else if (op_code == MAX_EXPR) - /* MAX (X, 0) > -1 -> true */ - return omit_one_operand_loc (loc, type, integer_one_node, inner); - - else if (op_code == MIN_EXPR && (consts_equal || consts_lt)) - /* MIN (X, 0) > 0 -> false - MIN (X, 0) > 5 -> false */ - return omit_one_operand_loc (loc, type, integer_zero_node, inner); - - else - /* MIN (X, 0) > -1 -> X > -1 */ - return fold_build2_loc (loc, GT_EXPR, type, inner, comp_const); - - default: - return NULL_TREE; - } -} - /* T is an integer expression that is being multiplied, divided, or taken a modulus (CODE says which and what kind of divide or modulus) by a constant C. See if we can eliminate that operation by folding it with other operations already in T. WIDE_TYPE, if non-null, is a type that should be used for the computation if wider than our type. For example, if we are dividing (X * 8) + (Y * 16) by 4, we can return (X * 2) + (Y * 4). We must, however, be assured that either the original expression would not overflow or that overflow is undefined for the type in the language in question. @@ -8712,32 +8606,20 @@ fold_comparison (location_t loc, enum tr TREE_TYPE (arg0), variable1, cst), variable2); } } tem = maybe_canonicalize_comparison (loc, code, type, arg0, arg1); if (tem) return tem; - /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a - constant, we can simplify it. */ - if (TREE_CODE (arg1) == INTEGER_CST - && (TREE_CODE (arg0) == MIN_EXPR - || TREE_CODE (arg0) == MAX_EXPR) - && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST) - { - tem = optimize_minmax_comparison (loc, code, type, op0, op1); - if (tem) - return tem; - } - /* If we are comparing an expression that just has comparisons of two integer values, arithmetic expressions of those comparisons, and constants, we can simplify it. There are only three cases to check: the two values can either be equal, the first can be greater, or the second can be greater. Fold the expression for those three values. Since each value must be 0 or 1, we have eight possibilities, each of which corresponds to the constant 0 or 1 or one of the six possible comparisons. This handles common cases like (a > b) == 0 but also handles Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 237336) +++ gcc/match.pd (working copy) @@ -1305,20 +1305,52 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))) (negate (maxmin @0 @1))))) /* MIN (~X, ~Y) -> ~MAX (X, Y) MAX (~X, ~Y) -> ~MIN (X, Y) */ (for minmax (min max) maxmin (max min) (simplify (minmax (bit_not:s@2 @0) (bit_not:s@3 @1)) (bit_not (maxmin @0 @1)))) +/* MIN (X, Y) == X -> X <= Y */ +(for minmax (min min max max) + cmp (eq ne eq ne ) + out (le gt ge lt ) + (simplify + (cmp:c (minmax:c @0 @1) @0) + (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))) + (out @0 @1)))) +/* MIN (X, 5) == 0 -> X == 0 + MIN (X, 5) == 7 -> false */ +(for cmp (eq ne) + (simplify + (cmp (min @0 INTEGER_CST@1) INTEGER_CST@2) + (if (wi::lt_p (@1, @2, TYPE_SIGN (TREE_TYPE (@0)))) + { constant_boolean_node (cmp == NE_EXPR, type); } + (if (wi::gt_p (@1, @2, TYPE_SIGN (TREE_TYPE (@0)))) + (cmp @0 @2))))) +(for cmp (eq ne) + (simplify + (cmp (max @0 INTEGER_CST@1) INTEGER_CST@2) + (if (wi::gt_p (@1, @2, TYPE_SIGN (TREE_TYPE (@0)))) + { constant_boolean_node (cmp == NE_EXPR, type); } + (if (wi::lt_p (@1, @2, TYPE_SIGN (TREE_TYPE (@0)))) + (cmp @0 @2))))) +/* MIN (X, C1) < C2 -> X < C2 || C1 < C2 */ +(for minmax (min min max max min min max max ) + cmp (lt le gt ge gt ge lt le ) + comb (bit_ior bit_ior bit_ior bit_ior bit_and bit_and bit_and bit_and) + (simplify + (cmp (minmax @0 INTEGER_CST@1) INTEGER_CST@2) + (comb (cmp @0 @2) (cmp @1 @2)))) + /* Simplifications of shift and rotates. */ (for rotate (lrotate rrotate) (simplify (rotate integer_all_onesp@0 @1) @0)) /* Optimize -1 >> x for arithmetic right shifts. */ (simplify (rshift integer_all_onesp@0 @1)