From patchwork Fri Apr 29 17:36:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 616917 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 3qxLVN4FRnz9t3f for ; Sat, 30 Apr 2016 03:36:59 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=RIUd4ZRw; 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:cc:subject:in-reply-to:message-id:references :mime-version:content-type; q=dns; s=default; b=Zg76PhPVxWzjqk0E ZwVlxSt2Labf06ukVy4Qkxms3cUm5Aluv8pJL/cx9yAVNvhU6kK2SpjMvr6iKN7p ztMMO6D/guhqd4iTSz2xGWG2LvRsKvVgZeJu/A/h8bzR7DR231OLB8ExginAY0+X 16U/aGGFkgjzsnylUs23P6jmBys= 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=xR8I/zYLC5Vz0fTsFBrsgK zncOw=; b=RIUd4ZRwgVWSJU2NpgOo+b3JdhAvpTP/zwnL0xifCd+Rom+Fbjyebs ueBFERxZB3m0VUYZSvvy37j5Fxca1lhBWFEzddKVzRPR6wAseRKCWPv41boeEJL5 8wpqp8aTC19UbFCOlX7dueahMw3D9XRp4IcW+WEGdvB2TUGNp5+GM= Received: (qmail 30044 invoked by alias); 29 Apr 2016 17:36:52 -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 30034 invoked by uid 89); 29 Apr 2016 17:36:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=sk:fold_ov, Worker, worker, marc.glisse@inria.fr 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 (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 29 Apr 2016 17:36:41 +0000 Received: from 81-65-27-132.rev.numericable.fr (HELO laptop-mg.local) ([81.65.27.132]) by mail3-relais-sop.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-SHA; 29 Apr 2016 19:36:37 +0200 Date: Fri, 29 Apr 2016 19:36:32 +0200 (CEST) From: Marc Glisse To: Richard Biener cc: GCC Patches Subject: Re: Move "X +- C1 CMP C2 to X CMP C2 -+ C1" to match.pd In-Reply-To: Message-ID: References: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 On Fri, 29 Apr 2016, Richard Biener wrote: > Another option is to move the enum declaration from flag-types.h to > coretypes.h. I think I like that best. This works. 2016-05-02 Marc Glisse gcc/ * flag-types.h (enum warn_strict_overflow_code): Move ... * coretypes.h: ... here. * fold-const.h (fold_overflow_warning): Declare. * fold-const.c (fold_overflow_warning): Make non-static. (fold_comparison): Move the transformation of X +- C1 CMP C2 into X CMP C2 -+ C1 ... * match.pd: ... here. * gimple-fold.c (fold_stmt_1): Protect with fold_defer_overflow_warnings. gcc/testsuite/ * gcc.dg/tree-ssa/20040305-1.c: Adjust. Index: gcc/coretypes.h =================================================================== --- gcc/coretypes.h (revision 235644) +++ gcc/coretypes.h (working copy) @@ -215,20 +215,44 @@ enum optimization_type { /* Possible initialization status of a variable. When requested by the user, this information is tracked and recorded in the DWARF debug information, along with the variable's location. */ enum var_init_status { VAR_INIT_STATUS_UNKNOWN, VAR_INIT_STATUS_UNINITIALIZED, VAR_INIT_STATUS_INITIALIZED }; +/* Names for the different levels of -Wstrict-overflow=N. The numeric + values here correspond to N. */ +enum warn_strict_overflow_code +{ + /* Overflow warning that should be issued with -Wall: a questionable + construct that is easy to avoid even when using macros. Example: + folding (x + CONSTANT > x) to 1. */ + WARN_STRICT_OVERFLOW_ALL = 1, + /* Overflow warning about folding a comparison to a constant because + of undefined signed overflow, other than cases covered by + WARN_STRICT_OVERFLOW_ALL. Example: folding (abs (x) >= 0) to 1 + (this is false when x == INT_MIN). */ + WARN_STRICT_OVERFLOW_CONDITIONAL = 2, + /* Overflow warning about changes to comparisons other than folding + them to a constant. Example: folding (x + 1 > 1) to (x > 0). */ + WARN_STRICT_OVERFLOW_COMPARISON = 3, + /* Overflow warnings not covered by the above cases. Example: + folding ((x * 10) / 5) to (x * 2). */ + WARN_STRICT_OVERFLOW_MISC = 4, + /* Overflow warnings about reducing magnitude of constants in + comparison. Example: folding (x + 2 > y) to (x + 1 >= y). */ + WARN_STRICT_OVERFLOW_MAGNITUDE = 5 +}; + /* The type of an alias set. Code currently assumes that variables of this type can take the values 0 (the alias set which aliases everything) and -1 (sometimes indicating that the alias set is unknown, sometimes indicating a memory barrier) and -2 (indicating that the alias set should be set to a unique value but has not been set yet). */ typedef int alias_set_type; struct edge_def; typedef struct edge_def *edge; Index: gcc/flag-types.h =================================================================== --- gcc/flag-types.h (revision 235644) +++ gcc/flag-types.h (working copy) @@ -171,44 +171,20 @@ enum stack_check_type /* Check the stack and rely on the target configuration files to check the static frame of functions, i.e. use the generic mechanism only for dynamic stack allocations. */ STATIC_BUILTIN_STACK_CHECK, /* Check the stack and entirely rely on the target configuration files, i.e. do not use the generic mechanism at all. */ FULL_BUILTIN_STACK_CHECK }; -/* Names for the different levels of -Wstrict-overflow=N. The numeric - values here correspond to N. */ -enum warn_strict_overflow_code -{ - /* Overflow warning that should be issued with -Wall: a questionable - construct that is easy to avoid even when using macros. Example: - folding (x + CONSTANT > x) to 1. */ - WARN_STRICT_OVERFLOW_ALL = 1, - /* Overflow warning about folding a comparison to a constant because - of undefined signed overflow, other than cases covered by - WARN_STRICT_OVERFLOW_ALL. Example: folding (abs (x) >= 0) to 1 - (this is false when x == INT_MIN). */ - WARN_STRICT_OVERFLOW_CONDITIONAL = 2, - /* Overflow warning about changes to comparisons other than folding - them to a constant. Example: folding (x + 1 > 1) to (x > 0). */ - WARN_STRICT_OVERFLOW_COMPARISON = 3, - /* Overflow warnings not covered by the above cases. Example: - folding ((x * 10) / 5) to (x * 2). */ - WARN_STRICT_OVERFLOW_MISC = 4, - /* Overflow warnings about reducing magnitude of constants in - comparison. Example: folding (x + 2 > y) to (x + 1 >= y). */ - WARN_STRICT_OVERFLOW_MAGNITUDE = 5 -}; - /* Floating-point contraction mode. */ enum fp_contract_mode { FP_CONTRACT_OFF = 0, FP_CONTRACT_ON = 1, FP_CONTRACT_FAST = 2 }; /* Scalar storage order kind. */ enum scalar_storage_order_kind { SSO_NATIVE = 0, Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 235644) +++ gcc/fold-const.c (working copy) @@ -290,21 +290,21 @@ fold_undefer_and_ignore_overflow_warning bool fold_deferring_overflow_warnings_p (void) { return fold_deferring_overflow_warnings > 0; } /* This is called when we fold something based on the fact that signed overflow is undefined. */ -static void +void fold_overflow_warning (const char* gmsgid, enum warn_strict_overflow_code wc) { if (fold_deferring_overflow_warnings > 0) { if (fold_deferred_overflow_warning == NULL || wc < fold_deferred_overflow_code) { fold_deferred_overflow_warning = gmsgid; fold_deferred_overflow_code = wc; } @@ -8388,89 +8388,20 @@ fold_comparison (location_t loc, enum tr { const bool equality_code = (code == EQ_EXPR || code == NE_EXPR); tree arg0, arg1, tem; arg0 = op0; arg1 = op1; STRIP_SIGN_NOPS (arg0); STRIP_SIGN_NOPS (arg1); - /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */ - if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) - && (equality_code - || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0)) - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0)))) - && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST - && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)) - && TREE_CODE (arg1) == INTEGER_CST - && !TREE_OVERFLOW (arg1)) - { - const enum tree_code - reverse_op = TREE_CODE (arg0) == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR; - tree const1 = TREE_OPERAND (arg0, 1); - tree const2 = fold_convert_loc (loc, TREE_TYPE (const1), arg1); - tree variable = TREE_OPERAND (arg0, 0); - tree new_const = int_const_binop (reverse_op, const2, const1); - - /* If the constant operation overflowed this can be - simplified as a comparison against INT_MAX/INT_MIN. */ - if (TREE_OVERFLOW (new_const) - && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))) - { - int const1_sgn = tree_int_cst_sgn (const1); - enum tree_code code2 = code; - - /* Get the sign of the constant on the lhs if the - operation were VARIABLE + CONST1. */ - if (TREE_CODE (arg0) == MINUS_EXPR) - const1_sgn = -const1_sgn; - - /* The sign of the constant determines if we overflowed - INT_MAX (const1_sgn == -1) or INT_MIN (const1_sgn == 1). - Canonicalize to the INT_MIN overflow by swapping the comparison - if necessary. */ - if (const1_sgn == -1) - code2 = swap_tree_comparison (code); - - /* We now can look at the canonicalized case - VARIABLE + 1 CODE2 INT_MIN - and decide on the result. */ - switch (code2) - { - case EQ_EXPR: - case LT_EXPR: - case LE_EXPR: - return - omit_one_operand_loc (loc, type, boolean_false_node, variable); - - case NE_EXPR: - case GE_EXPR: - case GT_EXPR: - return - omit_one_operand_loc (loc, type, boolean_true_node, variable); - - default: - gcc_unreachable (); - } - } - else - { - if (!equality_code) - fold_overflow_warning ("assuming signed overflow does not occur " - "when changing X +- C1 cmp C2 to " - "X cmp C2 -+ C1", - WARN_STRICT_OVERFLOW_COMPARISON); - return fold_build2_loc (loc, code, type, variable, new_const); - } - } - /* For comparisons of pointers we can decompose it to a compile time comparison of the base objects and the offsets into the object. This requires at least one operand being an ADDR_EXPR or a POINTER_PLUS_EXPR to do more than the operand_equal_p test below. */ if (POINTER_TYPE_P (TREE_TYPE (arg0)) && (TREE_CODE (arg0) == ADDR_EXPR || TREE_CODE (arg1) == ADDR_EXPR || TREE_CODE (arg0) == POINTER_PLUS_EXPR || TREE_CODE (arg1) == POINTER_PLUS_EXPR)) { Index: gcc/fold-const.h =================================================================== --- gcc/fold-const.h (revision 235644) +++ gcc/fold-const.h (working copy) @@ -79,20 +79,21 @@ extern bool fold_convertible_p (const_tr fold_convert_loc (UNKNOWN_LOCATION, T1, T2) extern tree fold_convert_loc (location_t, tree, tree); extern tree fold_single_bit_test (location_t, enum tree_code, tree, tree, tree); extern tree fold_ignored_result (tree); extern tree fold_abs_const (tree, tree); extern tree fold_indirect_ref_1 (location_t, tree, tree); extern void fold_defer_overflow_warnings (void); extern void fold_undefer_overflow_warnings (bool, const gimple *, int); extern void fold_undefer_and_ignore_overflow_warnings (void); extern bool fold_deferring_overflow_warnings_p (void); +extern void fold_overflow_warning (const char*, enum warn_strict_overflow_code); extern int operand_equal_p (const_tree, const_tree, unsigned int); 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) Index: gcc/gimple-fold.c =================================================================== --- gcc/gimple-fold.c (revision 235644) +++ gcc/gimple-fold.c (working copy) @@ -3518,21 +3518,23 @@ maybe_canonicalize_mem_ref_addr (tree *t } /* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE argument distinguishes both cases. */ static bool fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree)) { bool changed = false; gimple *stmt = gsi_stmt (*gsi); + bool nowarning = gimple_no_warning_p (stmt); unsigned i; + fold_defer_overflow_warnings (); /* First do required canonicalization of [TARGET_]MEM_REF addresses after propagation. ??? This shouldn't be done in generic folding but in the propagation helpers which also know whether an address was propagated. Also canonicalize operand order. */ switch (gimple_code (stmt)) { case GIMPLE_ASSIGN: @@ -3811,20 +3813,21 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, { tree new_lhs = maybe_fold_reference (lhs, true); if (new_lhs) { gimple_set_lhs (stmt, new_lhs); changed = true; } } } + fold_undefer_overflow_warnings (changed && !nowarning, stmt, 0); return changed; } /* Valueziation callback that ends up not following SSA edges. */ tree no_follow_ssa_edges (tree) { return NULL_TREE; } Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 235644) +++ gcc/match.pd (working copy) @@ -3179,10 +3179,54 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (simplify /* signbit(x) -> 0 if x is nonnegative. */ (SIGNBIT tree_expr_nonnegative_p@0) { integer_zero_node; }) (simplify /* signbit(x) -> x<0 if x doesn't have signed zeros. */ (SIGNBIT @0) (if (!HONOR_SIGNED_ZEROS (@0)) (convert (lt @0 { build_real (TREE_TYPE (@0), dconst0); })))) + +/* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */ +(for cmp (eq ne) + (for op (plus minus) + rop (minus plus) + (simplify + (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2) + (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2) + && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0)) + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@0)) + && !TYPE_SATURATING (TREE_TYPE (@0))) + (with { tree res = int_const_binop (rop, @2, @1); } + (if (TREE_OVERFLOW (res)) + { constant_boolean_node (cmp == NE_EXPR, type); } + (if (single_use (@3)) + (cmp @0 { res; })))))))) +(for cmp (lt le gt ge) + (for op (plus minus) + rop (minus plus) + (simplify + (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2) + (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + (with { tree res = int_const_binop (rop, @2, @1); } + (if (TREE_OVERFLOW (res)) + { + fold_overflow_warning (("assuming signed overflow does not occur " + "when simplifying conditional to constant"), + WARN_STRICT_OVERFLOW_CONDITIONAL); + bool less = cmp == LE_EXPR || cmp == LT_EXPR; + /* wi::ges_p (@2, 0) should be sufficient for a signed type. */ + bool ovf_high = wi::lt_p (@1, 0, TYPE_SIGN (TREE_TYPE (@1))) + != (op == MINUS_EXPR); + constant_boolean_node (less == ovf_high, type); + } + (if (single_use (@3)) + (with + { + fold_overflow_warning (("assuming signed overflow does not occur " + "when changing X +- C1 cmp C2 to " + "X cmp C2 -+ C1"), + WARN_STRICT_OVERFLOW_COMPARISON); + } + (cmp @0 { res; }))))))))) Index: gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c (revision 235644) +++ gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c (working copy) @@ -16,15 +16,15 @@ void foo(int edx, int eax) } if (eax == 100) { if (-- edx == 0) afred[0] = 2; } } /* Verify that we did a forward propagation. */ -/* { dg-final { scan-tree-dump-times "Replaced" 1 "forwprop1"} } */ +/* { dg-final { scan-tree-dump-times "gimple_simplified" 1 "forwprop1"} } */ /* After cddce we should have two IF statements remaining as the other two tests can be threaded. */ /* { dg-final { scan-tree-dump-times "if " 2 "cddce2"} } */