From patchwork Fri Sep 6 10:13:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 1158929 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508456-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="l4d6GDqn"; dkim-atps=neutral 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 46PtgD0K0bz9s7T for ; Fri, 6 Sep 2019 20:13:27 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:cc:references:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=tAaBDHzktgBesHdD7 /8JPg8n/GMtoO8UiAKPurle9vMy3M4shQIYS4GM2/xzrYQB2Q4E3cEj9hoj00wsU CtOJUL75kXdr1Gh5jRk+46gO84U5XIYAZha4UD1o50LWRI3KAmM1dmkdM1LfGwsr GJYhFfj45KNcX5WoWVw6xvGlsw= 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 :subject:to:cc:references:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=T9e8RfHxwjX3HRu05u9Pu8w e0+8=; b=l4d6GDqnQG6zc6TJu5JJklyFg5UrNmGgSUkMY+UNtqqJxa/u6bSxvww tQmdu5r4R+1kWHHNPMSB32hYFX7nY+Oy7RIUAZsKi5o5D9N5AOiE/tEfRi0RltUY og4DtK2ocPCmkz07He2oNGR/xsjhE88GHJcAHTeFU6j0Rot14BhM= Received: (qmail 80141 invoked by alias); 6 Sep 2019 10:13:19 -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 80010 invoked by uid 89); 6 Sep 2019 10:13:19 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-17.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy=gimple.c, gimplec, UD:gimple.c X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 06 Sep 2019 10:13:16 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 2D0E1AC37; Fri, 6 Sep 2019 10:13:14 +0000 (UTC) Subject: [PATCH 1/2] Auto-generate maybe_fold_and/or_comparisons from match.pd To: Richard Biener , Li Jia He Cc: Andrew Pinski , Jeff Law , GCC Patches , Segher Boessenkool , wschmidt@linux.ibm.com, Martin Liska References: <1561615913-22109-1-git-send-email-helijia@linux.ibm.com> <6fb28248-5134-cec5-5045-45253e4d2eb0@redhat.com> <6d333ccf-9905-e929-c2dc-fc611ff929f1@linux.ibm.com> <845bc280-7bd6-509b-3830-4ebde50f1b20@linux.ibm.com> From: =?utf-8?q?Martin_Li=C5=A1ka?= Message-ID: Date: Fri, 6 Sep 2019 12:13:12 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes On 9/5/19 3:01 PM, Richard Biener wrote: > On Tue, 16 Jul 2019, Li Jia He wrote: > >> Hi, >> >> I made some changes based on the recommendations. Would you like to >> help me to see it again ? Sorry, it took so long time to provide the >> patch. >> >> Note: 1. I keep the code for and_comparisons_1 and or_comparisons_1. >> The reason is that I did not found a good way to handle the >> optimization of '((x CODE1 y) AND (x CODE2 y))' in match.pd. >> Maybe I missing some important information about match.pd. >> 2. The gimple_resimplify2 function is not used. Since stmt1, >> stmt2, lhs1 and lhs2 are allocated on the stack, Is there a >> question with the value on the stack as the return value ? >> I may have misunderstood Richard's intention. > > Sorry for the delay in reviewing. > > Rather than exporting gimple_set_code and gimple_size I'd split > out a > > void > gimple_init (gimple *, enum gimple_code code, unsigned nops); > > from gimple_alloc (changing that to GC allocate not cleared > memory) doing all of the actual initialization. Then the > allocation would go like > > gimple *stmt1 = (gimple *)XALLOCAVEC (char, gimple_size (GIMPLE_ASSIGN, > 3)); > gimple_init (stmt1, GIMPLE_ASSIGN, 3); > > with an overload for gimple_size to account for # of ops. > > + /* Allocate SSA names(lhs1) on the stack. */ > + tree lhs1 = XALLOCA (tree_node); > > you can use (tree) XALLOCA (tree_ssa_name) here > > + /* Call the interface function of match.pd to simplify the expression. > */ > + tree t = gimple_simplify (code, boolean_type_node, gimple_assign_lhs > (stmt1), > + gimple_assign_lhs (stmt2), NULL, > + follow_all_ssa_edges); > + > + if (t) > > As I told Martin offline the appropriate function to use is > > You'd do > > gimple_match_op op (gimple_match_cond::UNCOND, code, > boolean_type_node, gimple_assign_lhs (stmt1), > gimple_assign_lhs (stmt2)); > if (op->resimplify (NULL, follow_all_ssa_edges)) > { > if (gimple_simplified_result_is_gimple_val (res_op)) > .. got a constant or SSA name .. > else if (res_op->code.is_tree_code () > && TREE_CODE_CLASS ((tree_code)res_op->code)) == > tcc_comparison) > ... got a comparison res_op->op[0] res_op->code res_op->op[1] ... > > so you get the outermost expression back decomposed. > > Otherwise with you passing NULL as the gimple_seq you'll miss quite > some simplification cases. > > You also have to watch out for the result containing the LHS of one > of your temporary stmts. > > + if (tree t = maybe_fold_comparisons_from_match_pd (BIT_AND_EXPR, code1, > op1a, > + op1b, code2, op2a, > op2b)) > + return t; > + > + if (tree t = maybe_fold_comparisons_from_match_pd (BIT_AND_EXPR, code2, > op2a, > + op2b, code1, op1a, > op1b)) > + return t; > > with match.pd rules you shouldn't need to call this twice, once with > swapped operands. > > Otherwise this first patch looks like what I'd have done and we > can build upon it. > > Not sure if you or Martin wants to improve it according to my > comments. > > Thanks, > Richard. > I'm sending patch that addresses the feedback from Richard. Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin From 6f8feb5ccf46bae2c65b88a90661e23521ce9143 Mon Sep 17 00:00:00 2001 From: Li Jia He Date: Mon, 15 Jul 2019 00:30:25 -0500 Subject: [PATCH 1/2] Auto-generate maybe_fold_and/or_comparisons from match.pd gcc/ChangeLog 2019-07-16 Li Jia He Martin Liska * gimple.h (gimple_init): Declare. (gimple_size): Likewise. * gimple.c (gimple_init): Remove static and inline restrictions. (gimple_alloc): Only allocate memory and call gimple_init. (gimple_size): Likewise. * gimple-fold.c (maybe_fold_comparisons_from_match_pd): New function. (maybe_fold_and_comparisons): Modify and_comparisons_1 invocation and call maybe_fold_comparisons_from_match_pd. (maybe_fold_or_comparisons): Modify or_comparisons_1 invocation and call maybe_fold_comparisons_from_match_pd. * tree-ssanames.c (init_ssa_name_imm_use): Use make_ssa_name_fn. (make_ssa_name_fn): New. * tree-ssanames.h (init_ssa_name_imm_use): New. --- gcc/gimple-fold.c | 108 ++++++++++++++++++++++++++++++++++++++++---- gcc/gimple.c | 37 +++++++++------ gcc/gimple.h | 2 + gcc/tree-ssanames.c | 21 ++++++--- gcc/tree-ssanames.h | 1 + 5 files changed, 138 insertions(+), 31 deletions(-) diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index fcffb9802b7..5a42d5bebee 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -5834,6 +5834,85 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, return NULL_TREE; } +/* Helper function for maybe_fold_and_comparisons and maybe_fold_or_comparisons + : try to simplify the AND/OR of the ssa variable VAR with the comparison + specified by (OP2A CODE2 OP2B) from match.pd. Return NULL_EXPR if we can't + simplify this to a single expression. As we are going to lower the cost + of building SSA names / gimple stmts significantly, we need to allocate + them ont the stack. This will cause the code to be a bit ugly. */ + +static tree +maybe_fold_comparisons_from_match_pd (enum tree_code code, enum tree_code code1, + tree op1a, tree op1b, + enum tree_code code2, tree op2a, + tree op2b) +{ + /* Allocate gimple stmt1 on the stack. */ + gimple *stmt1 = (gimple *) XALLOCAVEC (char, gimple_size (GIMPLE_ASSIGN, 2)); + gimple_init (stmt1, GIMPLE_ASSIGN, 3); + gimple_assign_set_rhs_code (stmt1, code1); + gimple_assign_set_rhs1 (stmt1, op1a); + gimple_assign_set_rhs2 (stmt1, op1b); + + /* Allocate gimple stmt2 on the stack. */ + gimple *stmt2 = (gimple *) XALLOCAVEC (char, gimple_size (GIMPLE_ASSIGN, 2)); + gimple_init (stmt2, GIMPLE_ASSIGN, 3); + gimple_assign_set_rhs_code (stmt2, code2); + gimple_assign_set_rhs1 (stmt2, op2a); + gimple_assign_set_rhs2 (stmt2, op2b); + + /* Allocate SSA names(lhs1) on the stack. */ + tree lhs1 = (tree)XALLOCA (tree_ssa_name); + memset (lhs1, 0, sizeof (tree_ssa_name)); + TREE_SET_CODE (lhs1, SSA_NAME); + TREE_TYPE (lhs1) = boolean_type_node; + init_ssa_name_imm_use (lhs1); + + /* Allocate SSA names(lhs2) on the stack. */ + tree lhs2 = (tree)XALLOCA (tree_ssa_name); + memset (lhs2, 0, sizeof (tree_ssa_name)); + TREE_SET_CODE (lhs2, SSA_NAME); + TREE_TYPE (lhs2) = boolean_type_node; + init_ssa_name_imm_use (lhs2); + + gimple_assign_set_lhs (stmt1, lhs1); + gimple_assign_set_lhs (stmt2, lhs2); + + gimple_match_op op (gimple_match_cond::UNCOND, code, + boolean_type_node, gimple_assign_lhs (stmt1), + gimple_assign_lhs (stmt2)); + if (op.resimplify (NULL, follow_all_ssa_edges)) + { + if (gimple_simplified_result_is_gimple_val (&op)) + { + tree res = op.ops[0]; + switch (TREE_CODE (res)) + { + case SSA_NAME: + { + gimple *def = SSA_NAME_DEF_STMT (res); + + if (!is_gimple_assign (def) + || TREE_CODE_CLASS (gimple_assign_rhs_code (def)) + != tcc_comparison) + return NULL_TREE; + + return fold_build2 (gimple_assign_rhs_code (def), + boolean_type_node, gimple_assign_rhs1 (def), + gimple_assign_rhs2 (def)); + } + case INTEGER_CST: + /* Fold expression to boolean_true_node or boolean_false_node. */ + return res; + default: + return NULL_TREE; + } + } + } + + return NULL_TREE; +} + /* Try to simplify the AND of two comparisons, specified by (OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively. If this can be simplified to a single expression (without requiring @@ -5845,11 +5924,17 @@ tree maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b) { - tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b); - if (t) + if (tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b)) return t; - else - return and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b); + + if (tree t = and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b)) + return t; + + if (tree t = maybe_fold_comparisons_from_match_pd (BIT_AND_EXPR, code1, op1a, + op1b, code2, op2a, op2b)) + return t; + + return NULL_TREE; } /* Helper function for or_comparisons_1: try to simplify the OR of the @@ -6309,13 +6394,18 @@ tree maybe_fold_or_comparisons (enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, tree op2b) { - tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b); - if (t) + if (tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b)) + return t; + + if (tree t = or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b)) return t; - else - return or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b); -} + if (tree t = maybe_fold_comparisons_from_match_pd (BIT_IOR_EXPR, code1, op1a, + op1b, code2, op2a, op2b)) + return t; + + return NULL_TREE; +} /* Fold STMT to a constant using VALUEIZE to valueize SSA names. diff --git a/gcc/gimple.c b/gcc/gimple.c index 633ef512a19..88250cad16b 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -110,10 +110,27 @@ gimple_set_code (gimple *g, enum gimple_code code) /* Return the number of bytes needed to hold a GIMPLE statement with code CODE. */ -static inline size_t -gimple_size (enum gimple_code code) +size_t +gimple_size (enum gimple_code code, unsigned num_ops) { - return gsstruct_code_size[gss_for_code (code)]; + size_t size = gsstruct_code_size[gss_for_code (code)]; + if (num_ops > 0) + size += (sizeof (tree) * (num_ops - 1)); + return size; +} + +/* Initialize GIMPLE statement G with CODE and NUM_OPS. */ + +void +gimple_init (gimple *g, enum gimple_code code, unsigned num_ops) +{ + gimple_set_code (g, code); + gimple_set_num_ops (g, num_ops); + + /* Do not call gimple_set_modified here as it has other side + effects and this tuple is still not completely built. */ + g->modified = 1; + gimple_init_singleton (g); } /* Allocate memory for a GIMPLE statement with code CODE and NUM_OPS @@ -125,10 +142,7 @@ gimple_alloc (enum gimple_code code, unsigned num_ops MEM_STAT_DECL) size_t size; gimple *stmt; - size = gimple_size (code); - if (num_ops > 0) - size += sizeof (tree) * (num_ops - 1); - + size = gimple_size (code, num_ops); if (GATHER_STATISTICS) { enum gimple_alloc_kind kind = gimple_alloc_kind (code); @@ -137,14 +151,7 @@ gimple_alloc (enum gimple_code code, unsigned num_ops MEM_STAT_DECL) } stmt = ggc_alloc_cleared_gimple_statement_stat (size PASS_MEM_STAT); - gimple_set_code (stmt, code); - gimple_set_num_ops (stmt, num_ops); - - /* Do not call gimple_set_modified here as it has other side - effects and this tuple is still not completely built. */ - stmt->modified = 1; - gimple_init_singleton (stmt); - + gimple_init (stmt, code, num_ops); return stmt; } diff --git a/gcc/gimple.h b/gcc/gimple.h index 55f5d0d33d9..cf1f8da5ae2 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1445,6 +1445,8 @@ extern enum gimple_statement_structure_enum const gss_for_code_[]; of comminucating the profile info to the builtin expanders. */ extern gimple *currently_expanding_gimple_stmt; +size_t gimple_size (enum gimple_code code, unsigned num_ops = 0); +void gimple_init (gimple *g, enum gimple_code code, unsigned num_ops); gimple *gimple_alloc (enum gimple_code, unsigned CXX_MEM_STAT_INFO); greturn *gimple_build_return (tree); void gimple_call_reset_alias_info (gcall *); diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 3911db9c26e..f7b638dba11 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -252,6 +252,19 @@ flush_ssaname_freelist (void) vec_safe_truncate (FREE_SSANAMES_QUEUE (cfun), 0); } +/* Initialize SSA_NAME_IMM_USE_NODE of a SSA NAME. */ + +void +init_ssa_name_imm_use (tree name) +{ + use_operand_p imm; + imm = &(SSA_NAME_IMM_USE_NODE (name)); + imm->use = NULL; + imm->prev = imm; + imm->next = imm; + imm->loc.ssa_name = name; +} + /* Return an SSA_NAME node for variable VAR defined in statement STMT in function FN. STMT may be an empty statement for artificial references (e.g., default definitions created when a variable is @@ -263,8 +276,6 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt, unsigned int version) { tree t; - use_operand_p imm; - gcc_assert (VAR_P (var) || TREE_CODE (var) == PARM_DECL || TREE_CODE (var) == RESULT_DECL @@ -318,11 +329,7 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt, SSA_NAME_IN_FREE_LIST (t) = 0; SSA_NAME_IS_DEFAULT_DEF (t) = 0; - imm = &(SSA_NAME_IMM_USE_NODE (t)); - imm->use = NULL; - imm->prev = imm; - imm->next = imm; - imm->loc.ssa_name = t; + init_ssa_name_imm_use (t); return t; } diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h index 6e6cffbce6a..1a7d0bccdf8 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -82,6 +82,7 @@ extern void fini_ssanames (struct function *); extern void ssanames_print_statistics (void); extern tree make_ssa_name_fn (struct function *, tree, gimple *, unsigned int version = 0); +extern void init_ssa_name_imm_use (tree); extern void release_ssa_name_fn (struct function *, tree); extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *, unsigned int *); -- 2.23.0 From patchwork Fri Sep 6 10:14:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 1158931 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508457-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="PV0RusC+"; dkim-atps=neutral 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 46Pth75hQxz9sNk for ; Fri, 6 Sep 2019 20:14:14 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:to:cc:references:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=SoC2o8y3BnPUb4v42 tL2Qz3rd5clqZPkvxklupvaJpsYpVdZDbivP2w4EnamBZ+BuzC9Tl/351DP5GZc9 dh0QwpLHV8Tqu/DS335IrphKpGm/s6sEl1cAfwOTSlYgVWWMa5UG2H6DxvChOB5G snxOMmJMU3m5YSFls2S+xhf+Ow= 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 :subject:to:cc:references:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=riCvk8AGcfF2/kdu251CS8k W6VU=; b=PV0RusC+EufjlwN8NhjNHIVynM0DaXElad39f5Fcg3GCN5tabFJIIXU +5+RGAebmGXEZknGYaaJF2sZ7qrwA3epzM8Z8pKtEHbl6/dccGD0Is0f8BG/3vWe rZ3kNwz8MKCKNid1sWEKbGVl9skwZM7gGWOJzWfQKiM7zRd4Zez8= Received: (qmail 82570 invoked by alias); 6 Sep 2019 10:14:06 -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 82561 invoked by uid 89); 6 Sep 2019 10:14:06 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-17.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy=D*3, Lijia, lijia X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 06 Sep 2019 10:14:03 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 12B6EAC37; Fri, 6 Sep 2019 10:14:01 +0000 (UTC) Subject: [PATCH 2/2] Fix PR88784, middle end is missing some optimizations about unsigned To: Richard Biener , Li Jia He Cc: Andrew Pinski , Jeff Law , GCC Patches , Segher Boessenkool , wschmidt@linux.ibm.com, Martin Liska References: <1561615913-22109-1-git-send-email-helijia@linux.ibm.com> <6fb28248-5134-cec5-5045-45253e4d2eb0@redhat.com> <6d333ccf-9905-e929-c2dc-fc611ff929f1@linux.ibm.com> <845bc280-7bd6-509b-3830-4ebde50f1b20@linux.ibm.com> From: =?utf-8?q?Martin_Li=C5=A1ka?= Message-ID: <54becf51-4b23-4b00-ac66-a7987de6089e@suse.cz> Date: Fri, 6 Sep 2019 12:14:00 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes On 9/5/19 3:17 PM, Richard Biener wrote: > On Tue, 16 Jul 2019, Li Jia He wrote: > >> Hi, >> >> I made some changes based on the recommendations. Would you like to >> help me to see it again ? Sorry, it took so long time to provide the >> patch. >> >> Note: 1. I keep the code for and_comparisons_1 and or_comparisons_1. >> The reason is that I did not found a good way to handle the >> optimization of '((x CODE1 y) AND (x CODE2 y))' in match.pd. >> Maybe I missing some important information about match.pd. >> 2. The gimple_resimplify2 function is not used. Since stmt1, >> stmt2, lhs1 and lhs2 are allocated on the stack, Is there a >> question with the value on the stack as the return value ? >> I may have misunderstood Richard's intention. > > And now for the match.pd patch. > > +/* x > y && x != XXX_MIN --> x > y */ > +(for and (truth_and bit_and) > + (simplify > + (and:c (gt:c@3 @0 @1) (ne @0 INTEGER_CST@2)) > + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P > (TREE_TYPE(@1)) > + && (wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2))))) > + @3))) > + > +/* x > y && x == XXX_MIN --> false */ > +(for and (truth_and bit_and) > + (simplify > + (and:c (gt:c @0 @1) (eq @0 INTEGER_CST@2)) > + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P > (TREE_TYPE(@1)) > + && (wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2))))) > + { boolean_false_node; }))) > > you could merge those two via > > (for eqne (eq ne) > (for and (.... > (simplify > (and:c (gt:c @0 @1) (eqne @0 INTEGER_CST@2)) > (if (...) > (switch > (if (eqne == NE_EXPR) > @3) > (if (eqne == EQ_EXPR) > { constant_boolean_node (false, type); })))) > > notice using constant_boolean_node (false, type); instead of > boolean_false_node. I suspect more unification is possible. > > Also you could do > > (match min_value > INTEGER_CST > (if (INTEGRAL_TYPE_P (type) > && wi::eq_p (wi::to_wide (t), wi::min_value (type))))) > > and then write > > (simplify > (and:c (gt:c @0 @1) (eq @0 min_value)) > (... > > Your > > (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P > (TREE_TYPE(@1)) > > is redundant, it's enough to check either @0 or @1 given they > have to be compatible for the gt operation. Note you probably > want to use > > (and:c (gt:c @0 @1) (eq @@0 min_value)) > > and verify that types_match (@1, @0) because when @0 are a constant > (and (eq @0 min_value) is not folded which can happen) then they > might have different types and thus you could have > (SHORT_MAX > intvar) && (SHORT_MAX == SHORT_MAX) > > That said, the patterns can be quite a bit simplified I think. > > Richard. > Likewise, I applied the suggested simplification. Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin From 1006e2cf69e97692e09e845eaadf55098d48f0e2 Mon Sep 17 00:00:00 2001 From: Li Jia He Date: Mon, 15 Jul 2019 03:50:34 -0500 Subject: [PATCH 2/2] Fix PR88784, middle end is missing some optimizations about unsigned Hi, According to the optimizable case described by Qi Feng on issue 88784, we can combine the cases into the following: 1. x > y && x != XXX_MIN --> x > y 2. x > y && x == XXX_MIN --> false 3. x <= y && x == XXX_MIN --> x == XXX_MIN 4. x < y && x != XXX_MAX --> x < y 5. x < y && x == XXX_MAX --> false 6. x >= y && x == XXX_MAX --> x == XXX_MAX 7. x > y || x != XXX_MIN --> x != XXX_MIN 8. x <= y || x != XXX_MIN --> true 9. x <= y || x == XXX_MIN --> x <= y 10. x < y || x != XXX_MAX --> x != UXXX_MAX 11. x >= y || x != XXX_MAX --> true 12. x >= y || x == XXX_MAX --> x >= y Note: XXX_MIN represents the minimum value of type x. XXX_MAX represents the maximum value of type x. Here we don't need to care about whether the operation is signed or unsigned. For example, in the below equation: 'x > y && x != XXX_MIN --> x > y' If the x type is signed int and XXX_MIN is INT_MIN, we can optimize it to 'x > y'. However, if the type of x is unsigned int and XXX_MIN is 0, we can still optimize it to 'x > y'. The regression testing for the patch was done on GCC mainline on powerpc64le-unknown-linux-gnu (Power 9 LE) with no regressions. Is it OK for trunk ? Thanks, Lijia He gcc/ChangeLog 2019-07-16 Li Jia He Qi Feng PR middle-end/88784 * match.pd (x > y && x != XXX_MIN): Optimize into 'x > y'. (x > y && x == XXX_MIN): Optimize into 'false'. (x <= y && x == XXX_MIN): Optimize into 'x == XXX_MIN'. (x < y && x != XXX_MAX): Optimize into 'x < y'. (x < y && x == XXX_MAX): Optimize into 'false'. (x >= y && x == XXX_MAX): Optimize into 'x == XXX_MAX'. (x > y || x != XXX_MIN): Optimize into 'x != XXX_MIN'. (x <= y || x != XXX_MIN): Optimize into 'true'. (x <= y || x == XXX_MIN): Optimize into 'x <= y'. (x < y || x != XXX_MAX): Optimize into 'x != XXX_MAX'. (x >= y || x != XXX_MAX): Optimize into 'true'. (x >= y || x == XXX_MAX): Optimize into 'x >= y'. gcc/testsuite/ChangeLog 2019-07-16 Li Jia He Qi Feng PR middle-end/88784 * gcc.dg/pr88784-1.c: New testcase. * gcc.dg/pr88784-2.c: New testcase. * gcc.dg/pr88784-3.c: New testcase. * gcc.dg/pr88784-4.c: New testcase. * gcc.dg/pr88784-5.c: New testcase. * gcc.dg/pr88784-6.c: New testcase. * gcc.dg/pr88784-7.c: New testcase. * gcc.dg/pr88784-8.c: New testcase. * gcc.dg/pr88784-9.c: New testcase. * gcc.dg/pr88784-10.c: New testcase. * gcc.dg/pr88784-11.c: New testcase. * gcc.dg/pr88784-12.c: New testcase. --- gcc/match.pd | 91 +++++++++++++++++++++++++++++-- gcc/testsuite/gcc.dg/pr88784-1.c | 30 ++++++++++ gcc/testsuite/gcc.dg/pr88784-10.c | 32 +++++++++++ gcc/testsuite/gcc.dg/pr88784-11.c | 30 ++++++++++ gcc/testsuite/gcc.dg/pr88784-12.c | 30 ++++++++++ gcc/testsuite/gcc.dg/pr88784-2.c | 30 ++++++++++ gcc/testsuite/gcc.dg/pr88784-3.c | 32 +++++++++++ gcc/testsuite/gcc.dg/pr88784-4.c | 32 +++++++++++ gcc/testsuite/gcc.dg/pr88784-5.c | 31 +++++++++++ gcc/testsuite/gcc.dg/pr88784-6.c | 31 +++++++++++ gcc/testsuite/gcc.dg/pr88784-7.c | 31 +++++++++++ gcc/testsuite/gcc.dg/pr88784-8.c | 31 +++++++++++ gcc/testsuite/gcc.dg/pr88784-9.c | 32 +++++++++++ 13 files changed, 459 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr88784-1.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-10.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-11.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-12.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-2.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-3.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-4.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-5.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-6.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-7.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-8.c create mode 100644 gcc/testsuite/gcc.dg/pr88784-9.c diff --git a/gcc/match.pd b/gcc/match.pd index cd75dacd9cd..aa65cb63ca2 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1860,6 +1860,89 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) { wide_int_to_tree (type, (wi::to_wide (@1) & (bitpos / BITS_PER_UNIT))); })))) +(match min_value + INTEGER_CST + (if (INTEGRAL_TYPE_P (type) + && wi::eq_p (wi::to_wide (t), wi::min_value (type))))) + +(match max_value + INTEGER_CST + (if (INTEGRAL_TYPE_P (type) + && wi::eq_p (wi::to_wide (t), wi::max_value (type))))) + +/* x > y && x != XXX_MIN --> x > y + x > y && x == XXX_MIN --> false . */ +(for eqne (eq ne) + (for and (truth_and bit_and) + (simplify + (and:c (gt:c@2 @0 @1) (eqne @0 min_value)) + (switch + (if (eqne == EQ_EXPR) + { constant_boolean_node (false, type); }) + (if (eqne == NE_EXPR) + @2) + )))) + +/* x < y && x != XXX_MAX --> x < y + x < y && x == XXX_MAX --> false. */ +(for eqne (eq ne) + (for and (truth_and bit_and) + (simplify + (and:c (lt:c@2 @0 @1) (eqne @0 max_value)) + (switch + (if (eqne == EQ_EXPR) + { constant_boolean_node (false, type); }) + (if (eqne == NE_EXPR) + @2) + )))) + +/* x <= y && x == XXX_MIN --> x == XXX_MIN. */ +(for and (truth_and bit_and) + (simplify + (and:c (le:c @0 @1) (eq@2 @0 min_value)) + @2)) + +/* x >= y && x == XXX_MAX --> x == XXX_MAX. */ +(for and (truth_and bit_and) + (simplify + (and:c (ge:c @0 @1) (eq@2 @0 max_value)) + @2)) + +/* x > y || x != XXX_MIN --> x != XXX_MIN. */ +(for or (truth_or bit_ior) + (simplify + (or:c (gt:c @0 @1) (ne@2 @0 min_value)) + @2)) + +/* x <= y || x != XXX_MIN --> true. */ +(for or (truth_or bit_ior) + (simplify + (or:c (le:c @0 @1) (ne @0 min_value)) + { constant_boolean_node (true, type); })) + +/* x <= y || x == XXX_MIN --> x <= y. */ +(for or (truth_or bit_ior) + (simplify + (or:c (le:c@2 @0 @1) (eq @0 min_value)) + @2)) + +/* x < y || x != XXX_MAX --> x != XXX_MAX. */ +(for or (truth_or bit_ior) + (simplify + (or:c (lt:c @0 @1) (ne@2 @0 max_value)) + @2)) + +/* x >= y || x != XXX_MAX --> true + x >= y || x == XXX_MAX --> x >= y. */ +(for eqne (eq ne) + (for or (truth_or bit_ior) + (simplify + (or:c (ge:c@2 @0 @1) (eqne @0 max_value)) + (switch + (if (eqne == EQ_EXPR) + @2) + (if (eqne == NE_EXPR) + { constant_boolean_node (true, type); }))))) /* We can't reassociate at all for saturating types. */ (if (!TYPE_SATURATING (type)) @@ -5402,10 +5485,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) on c, so could drop potentially-trapping arithmetic, but that's a valid simplification if the result of the operation isn't needed. - Avoid speculatively generating a stand-alone vector comparison - on targets that might not support them. Any target implementing - conditional internal functions must support the same comparisons - inside and outside a VEC_COND_EXPR. */ + Avoid speculatively generating a stand-alone vector comparison + on targets that might not support them. Any target implementing + conditional internal functions must support the same comparisons + inside and outside a VEC_COND_EXPR. */ #if GIMPLE (for uncond_op (UNCOND_BINARY) diff --git a/gcc/testsuite/gcc.dg/pr88784-1.c b/gcc/testsuite/gcc.dg/pr88784-1.c new file mode 100644 index 00000000000..067d40d0739 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-1.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine --param logical-op-non-short-circuit=0" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x > y && x != 0 --> x > y */ + return x > y && x != 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x < y && x != UINT_MAX --> x < y */ + return x < y && x != UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x > y && x != INT_MIN --> x > y */ + return x > y && x != INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x < y && x != INT_MAX --> x < y */ + return x < y && x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " != " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-10.c b/gcc/testsuite/gcc.dg/pr88784-10.c new file mode 100644 index 00000000000..2218faa3b7c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-10.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple --param logical-op-non-short-circuit=1" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x <= y || x != 0 --> true */ + return x <= y || x != 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x >= y || x != UINT_MAX --> true */ + return x >= y || x != UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x <= y || x != INT_MIN --> true */ + return x <= y || x != INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x >= y || x != INT_MAX --> true */ + return x >= y || x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " != " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " <= " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " >= " "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-11.c b/gcc/testsuite/gcc.dg/pr88784-11.c new file mode 100644 index 00000000000..4465910efbb --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-11.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine --param logical-op-non-short-circuit=0" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x <= y || x == 0 --> x <= y */ + return x <= y || x == 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x >= y || x == UINT_MAX --> x >= y */ + return x >= y || x == UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x <= y || x == INT_MIN --> x <= y */ + return x <= y || x == INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x >= y || x == INT_MAX --> x >= y */ + return x >= y || x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " == " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-12.c b/gcc/testsuite/gcc.dg/pr88784-12.c new file mode 100644 index 00000000000..477bba07821 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-12.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dce3 --param logical-op-non-short-circuit=1" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x <= y || x == 0 --> x <= y */ + return x <= y || x == 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x >= y || x == UINT_MAX --> x >= y */ + return x >= y || x == UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x <= y || x == INT_MIN --> x <= y */ + return x <= y || x == INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x >= y || x == INT_MAX --> x >= y */ + return x >= y || x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " == " "dce3" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-2.c b/gcc/testsuite/gcc.dg/pr88784-2.c new file mode 100644 index 00000000000..02647204726 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-2.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple --param logical-op-non-short-circuit=1" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x > y && x != 0 --> x > y */ + return x > y && x != 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x < y && x != UINT_MAX --> x < y */ + return x < y && x != UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x > y && x != INT_MIN --> x > y */ + return x > y && x != INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x < y && x != INT_MAX --> x < y */ + return x < y && x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " != " "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-3.c b/gcc/testsuite/gcc.dg/pr88784-3.c new file mode 100644 index 00000000000..be2ce315e60 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-3.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine --param logical-op-non-short-circuit=0" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x > y && x == 0 --> false */ + return x > y && x == 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x < y && x == UINT_MAX --> false */ + return x < y && x == UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x > y && x == INT_MIN --> false */ + return x > y && x == INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x < y && x == INT_MAX --> false */ + return x < y && x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " == " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " > " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " < " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-4.c b/gcc/testsuite/gcc.dg/pr88784-4.c new file mode 100644 index 00000000000..d1363659f40 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-4.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple --param logical-op-non-short-circuit=1" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x > y && x == 0 --> false */ + return x > y && x == 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x < y && x == UINT_MAX --> false */ + return x < y && x == UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x > y && x == INT_MIN --> false */ + return x > y && x == INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x < y && x == INT_MAX --> false */ + return x < y && x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " == " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " > " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " < " "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-5.c b/gcc/testsuite/gcc.dg/pr88784-5.c new file mode 100644 index 00000000000..c6a349d7c75 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-5.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine --param logical-op-non-short-circuit=0" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x <= y && x == 0 --> x == 0 */ + return x <= y && x == 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x >= y && x == UINT_MAX --> x == UINT_MAX */ + return x >= y && x == UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x <= y && x == INT_MIN --> x == INT_MIN */ + return x <= y && x == INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x >= y && x == INT_MAX --> x == INT_MAX */ + return x >= y && x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " <= " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " >= " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-6.c b/gcc/testsuite/gcc.dg/pr88784-6.c new file mode 100644 index 00000000000..b0e81e0165e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-6.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple --param logical-op-non-short-circuit=1" } */ + +#include + +_Bool and1(unsigned x, unsigned y) +{ + /* x <= y && x == 0 --> x == 0 */ + return x <= y && x == 0; +} + +_Bool and2(unsigned x, unsigned y) +{ + /* x >= y && x == UINT_MAX --> x == UINT_MAX */ + return x >= y && x == UINT_MAX; +} + +_Bool and3(signed x, signed y) +{ + /* x <= y && x == INT_MIN --> x == INT_MIN */ + return x <= y && x == INT_MIN; +} + +_Bool and4(signed x, signed y) +{ + /* x >= y && x == INT_MAX --> x == INT_MAX */ + return x >= y && x == INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " <= " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " >= " "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-7.c b/gcc/testsuite/gcc.dg/pr88784-7.c new file mode 100644 index 00000000000..937d2d26593 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-7.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine --param logical-op-non-short-circuit=0" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x > y || x != 0 --> x != 0 */ + return x > y || x != 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x < y || x != UINT_MAX --> x != UINT_MAX */ + return x < y || x != UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x > y || x != INT_MIN --> x != INT_MIN */ + return x > y || x != INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x < y || x != INT_MAX --> x != INT_MAX */ + return x < y || x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " > " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " < " "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-8.c b/gcc/testsuite/gcc.dg/pr88784-8.c new file mode 100644 index 00000000000..aa384c305b1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-8.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple --param logical-op-non-short-circuit=1" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x > y || x != 0 --> x != 0 */ + return x > y || x != 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x < y || x != UINT_MAX --> x != UINT_MAX */ + return x < y || x != UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x > y || x != INT_MIN --> x != INT_MIN */ + return x > y || x != INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x < y || x != INT_MAX --> x != INT_MAX */ + return x < y || x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " > " "gimple" } } */ +/* { dg-final { scan-tree-dump-not " < " "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/pr88784-9.c b/gcc/testsuite/gcc.dg/pr88784-9.c new file mode 100644 index 00000000000..94f62d94ede --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr88784-9.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine --param logical-op-non-short-circuit=0" } */ + +#include + +_Bool or1(unsigned x, unsigned y) +{ + /* x <= y || x != 0 --> true */ + return x <= y || x != 0; +} + +_Bool or2(unsigned x, unsigned y) +{ + /* x >= y || x != UINT_MAX --> true */ + return x >= y || x != UINT_MAX; +} + +_Bool or3(signed x, signed y) +{ + /* x <= y || x != INT_MIN --> true */ + return x <= y || x != INT_MIN; +} + +_Bool or4(signed x, signed y) +{ + /* x >= y || x != INT_MAX --> true */ + return x >= y || x != INT_MAX; +} + +/* { dg-final { scan-tree-dump-not " != " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " <= " "ifcombine" } } */ +/* { dg-final { scan-tree-dump-not " >= " "ifcombine" } } */ -- 2.23.0 From patchwork Mon Sep 9 12:24:01 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 1159694 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508612-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="YwO3NFBF"; dkim-atps=neutral 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 46RnQy6y6Gz9s7T for ; Mon, 9 Sep 2019 22:24:26 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:from:to:cc:references:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=PptRBaq/4RqNnDZP1 WqQzqpjLz5wH9DHXxATzgu7kTAteG9Mpqm4EAC8qD8wehqeiPoNoYXRJV3UHmHDn 9b+HPWQdroq7Jo60wounKNu1kqFe1vif0klayr6L5UEMFuVgS7Gynr+ejKeNtPQq e7wR85wDtkBTgrRJazS/34ItVs= 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 :subject:from:to:cc:references:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=VnaGq11xbQfJIQ4DEegKmnF 8bVk=; b=YwO3NFBFfj2U6puQK3e8FE2hVE07JKAq5RtgiP57494QiNoBLGC5v/K aUW40+Cr36RhWevKWW+67vLVxW+jn921Z9rT8a2Gm4hUKG+ysLK+LssVOuwF6G38 EnakfZf/x7j5K0d0QTozn8eTcXpIX23rGsMwSU4z3VJkZbWzAlb0= Received: (qmail 41184 invoked by alias); 9 Sep 2019 12:24:08 -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 40463 invoked by uid 89); 9 Sep 2019 12:24:07 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-17.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy=name's, kids, bit_and X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 12:24:03 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 911A6AF38; Mon, 9 Sep 2019 12:24:01 +0000 (UTC) Subject: [PATCH 3/5] Rewrite part of and_comparisons_1 into match.pd. From: =?utf-8?q?Martin_Li=C5=A1ka?= To: Richard Biener , Li Jia He Cc: Andrew Pinski , Jeff Law , GCC Patches , Segher Boessenkool , wschmidt@linux.ibm.com, Martin Liska References: <1561615913-22109-1-git-send-email-helijia@linux.ibm.com> <6fb28248-5134-cec5-5045-45253e4d2eb0@redhat.com> <6d333ccf-9905-e929-c2dc-fc611ff929f1@linux.ibm.com> <845bc280-7bd6-509b-3830-4ebde50f1b20@linux.ibm.com> Message-ID: Date: Mon, 9 Sep 2019 14:24:01 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes Hi. The patch is about transition of and_comparisons_1 matching into match.pd. Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin From 15045058d6caf84734ea949a297b6e31d9a8647c Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Fri, 6 Sep 2019 12:34:49 +0200 Subject: [PATCH 3/5] Rewrite part of and_comparisons_1 into match.pd. gcc/ChangeLog: 2019-09-09 Martin Liska * genmatch.c (dt_node::append_simplify): Ignore warning for the same location. * gimple-fold.c (same_bool_result_p): Handle newly created SSA_NAMEs ar arguments. (and_comparisons_1): Add new argument gimple_stmt_iterator. (and_var_with_comparison): Likewise. (and_var_with_comparison_1): Likewise. (or_comparisons_1): Likewise. (or_var_with_comparison): Likewise. (or_var_with_comparison_1): Likewise. (maybe_fold_comparisons_from_match_pd): Handle creation of temporary SSA_NAMEs. Add new argument gimple_stmt_iterator. (maybe_fold_and_comparisons): Likewise. (maybe_fold_or_comparisons): Likewise. * gimple-fold.h (maybe_fold_and_comparisons): Likewise. (maybe_fold_or_comparisons): Likewise. * match.pd: Add rules for (X OP1 CST1) && (X OP2 CST2). * tree-if-conv.c (fold_or_predicates): Do not pass gimple_stmt_iterator. * tree-ssa-ifcombine.c (ifcombine_ifandif): Pass gimple_stmt_iterator. * tree-ssa-reassoc.c (eliminate_redundant_comparison): Do not pass gimple_stmt_iterator. (optimize_vec_cond_expr): Likewise. --- gcc/genmatch.c | 4 +- gcc/gimple-fold.c | 261 +++++++++++++-------------------------- gcc/gimple-fold.h | 6 +- gcc/match.pd | 68 ++++++++++ gcc/tree-if-conv.c | 2 +- gcc/tree-ssa-ifcombine.c | 5 +- gcc/tree-ssa-reassoc.c | 11 +- 7 files changed, 172 insertions(+), 185 deletions(-) diff --git a/gcc/genmatch.c b/gcc/genmatch.c index 2e7bf27eeda..b7194448a0f 100644 --- a/gcc/genmatch.c +++ b/gcc/genmatch.c @@ -1894,9 +1894,11 @@ dt_node * dt_node::append_simplify (simplify *s, unsigned pattern_no, dt_operand **indexes) { + dt_simplify *s2; dt_simplify *n = new dt_simplify (s, pattern_no, indexes); for (unsigned i = 0; i < kids.length (); ++i) - if (dt_simplify *s2 = dyn_cast (kids[i])) + if ((s2 = dyn_cast (kids[i])) + && s->match->location != s2->s->match->location) { warning_at (s->match->location, "duplicate pattern"); warning_at (s2->s->match->location, "previous pattern defined here"); diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 8a9eca13b87..f9971c004b7 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -5350,6 +5350,19 @@ same_bool_result_p (const_tree op1, const_tree op2) if (operand_equal_p (op1, op2, 0)) return true; + /* Function maybe_fold_comparisons_from_match_pd creates temporary + SSA_NAMEs. */ + if (TREE_CODE (op1) == SSA_NAME && TREE_CODE (op2) == SSA_NAME) + { + gimple *s = SSA_NAME_DEF_STMT (op2); + if (is_gimple_assign (s)) + return same_bool_comparison_p (op1, gimple_assign_rhs_code (s), + gimple_assign_rhs1 (s), + gimple_assign_rhs2 (s)); + else + return false; + } + /* Check the cases where at least one of the operands is a comparison. These are a bit smarter than operand_equal_p in that they apply some identifies on SSA_NAMEs. */ @@ -5372,22 +5385,28 @@ same_bool_result_p (const_tree op1, const_tree op2) static tree and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree and_var_with_comparison (tree var, bool invert, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree and_var_with_comparison_1 (gimple *stmt, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree or_var_with_comparison (tree var, bool invert, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); static tree or_var_with_comparison_1 (gimple *stmt, - enum tree_code code2, tree op2a, tree op2b); + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi); /* Helper function for and_comparisons_1: try to simplify the AND of the ssa variable VAR with the comparison specified by (OP2A CODE2 OP2B). @@ -5396,7 +5415,8 @@ or_var_with_comparison_1 (gimple *stmt, static tree and_var_with_comparison (tree var, bool invert, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree t; gimple *stmt = SSA_NAME_DEF_STMT (var); @@ -5411,9 +5431,9 @@ and_var_with_comparison (tree var, bool invert, if (invert) t = or_var_with_comparison_1 (stmt, invert_tree_comparison (code2, false), - op2a, op2b); + op2a, op2b, gsi); else - t = and_var_with_comparison_1 (stmt, code2, op2a, op2b); + t = and_var_with_comparison_1 (stmt, code2, op2a, op2b, gsi); return canonicalize_bool (t, invert); } @@ -5423,7 +5443,8 @@ and_var_with_comparison (tree var, bool invert, static tree and_var_with_comparison_1 (gimple *stmt, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree var = gimple_assign_lhs (stmt); tree true_test_var = NULL_TREE; @@ -5456,9 +5477,7 @@ and_var_with_comparison_1 (gimple *stmt, tree t = and_comparisons_1 (innercode, gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt), - code2, - op2a, - op2b); + code2, op2a, op2b, gsi); if (t) return t; } @@ -5489,11 +5508,13 @@ and_var_with_comparison_1 (gimple *stmt, else if (inner1 == false_test_var) return (is_and ? boolean_false_node - : and_var_with_comparison (inner2, false, code2, op2a, op2b)); + : and_var_with_comparison (inner2, false, code2, op2a, op2b, + gsi)); else if (inner2 == false_test_var) return (is_and ? boolean_false_node - : and_var_with_comparison (inner1, false, code2, op2a, op2b)); + : and_var_with_comparison (inner1, false, code2, op2a, op2b, + gsi)); /* Next, redistribute/reassociate the AND across the inner tests. Compute the first partial result, (inner1 AND (op2a code op2b)) */ @@ -5503,7 +5524,7 @@ and_var_with_comparison_1 (gimple *stmt, && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), - code2, op2a, op2b))) + code2, op2a, op2b, gsi))) { /* Handle the AND case, where we are reassociating: (inner1 AND inner2) AND (op2a code2 op2b) @@ -5535,7 +5556,7 @@ and_var_with_comparison_1 (gimple *stmt, && (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), - code2, op2a, op2b))) + code2, op2a, op2b, gsi))) { /* Handle the AND case, where we are reassociating: (inner1 AND inner2) AND (op2a code2 op2b) @@ -5589,7 +5610,8 @@ and_var_with_comparison_1 (gimple *stmt, static tree and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree truth_type = truth_type_for (TREE_TYPE (op1a)); @@ -5618,136 +5640,6 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, return t; } - /* If both comparisons are of the same value against constants, we might - be able to merge them. */ - if (operand_equal_p (op1a, op2a, 0) - && TREE_CODE (op1b) == INTEGER_CST - && TREE_CODE (op2b) == INTEGER_CST) - { - int cmp = tree_int_cst_compare (op1b, op2b); - - /* If we have (op1a == op1b), we should either be able to - return that or FALSE, depending on whether the constant op1b - also satisfies the other comparison against op2b. */ - if (code1 == EQ_EXPR) - { - bool done = true; - bool val; - switch (code2) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp < 0); break; - case GT_EXPR: val = (cmp > 0); break; - case LE_EXPR: val = (cmp <= 0); break; - case GE_EXPR: val = (cmp >= 0); break; - default: done = false; - } - if (done) - { - if (val) - return fold_build2 (code1, boolean_type_node, op1a, op1b); - else - return boolean_false_node; - } - } - /* Likewise if the second comparison is an == comparison. */ - else if (code2 == EQ_EXPR) - { - bool done = true; - bool val; - switch (code1) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp > 0); break; - case GT_EXPR: val = (cmp < 0); break; - case LE_EXPR: val = (cmp >= 0); break; - case GE_EXPR: val = (cmp <= 0); break; - default: done = false; - } - if (done) - { - if (val) - return fold_build2 (code2, boolean_type_node, op2a, op2b); - else - return boolean_false_node; - } - } - - /* Same business with inequality tests. */ - else if (code1 == NE_EXPR) - { - bool val; - switch (code2) - { - case EQ_EXPR: val = (cmp != 0); break; - case NE_EXPR: val = (cmp == 0); break; - case LT_EXPR: val = (cmp >= 0); break; - case GT_EXPR: val = (cmp <= 0); break; - case LE_EXPR: val = (cmp > 0); break; - case GE_EXPR: val = (cmp < 0); break; - default: - val = false; - } - if (val) - return fold_build2 (code2, boolean_type_node, op2a, op2b); - } - else if (code2 == NE_EXPR) - { - bool val; - switch (code1) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp <= 0); break; - case GT_EXPR: val = (cmp >= 0); break; - case LE_EXPR: val = (cmp < 0); break; - case GE_EXPR: val = (cmp > 0); break; - default: - val = false; - } - if (val) - return fold_build2 (code1, boolean_type_node, op1a, op1b); - } - - /* Chose the more restrictive of two < or <= comparisons. */ - else if ((code1 == LT_EXPR || code1 == LE_EXPR) - && (code2 == LT_EXPR || code2 == LE_EXPR)) - { - if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR)) - return fold_build2 (code1, boolean_type_node, op1a, op1b); - else - return fold_build2 (code2, boolean_type_node, op2a, op2b); - } - - /* Likewise chose the more restrictive of two > or >= comparisons. */ - else if ((code1 == GT_EXPR || code1 == GE_EXPR) - && (code2 == GT_EXPR || code2 == GE_EXPR)) - { - if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR)) - return fold_build2 (code1, boolean_type_node, op1a, op1b); - else - return fold_build2 (code2, boolean_type_node, op2a, op2b); - } - - /* Check for singleton ranges. */ - else if (cmp == 0 - && ((code1 == LE_EXPR && code2 == GE_EXPR) - || (code1 == GE_EXPR && code2 == LE_EXPR))) - return fold_build2 (EQ_EXPR, boolean_type_node, op1a, op2b); - - /* Check for disjoint ranges. */ - else if (cmp <= 0 - && (code1 == LT_EXPR || code1 == LE_EXPR) - && (code2 == GT_EXPR || code2 == GE_EXPR)) - return boolean_false_node; - else if (cmp >= 0 - && (code1 == GT_EXPR || code1 == GE_EXPR) - && (code2 == LT_EXPR || code2 == LE_EXPR)) - return boolean_false_node; - } - /* Perhaps the first comparison is (NAME != 0) or (NAME == 1) where NAME's definition is a truth value. See if there are any simplifications that can be done against the NAME's definition. */ @@ -5762,7 +5654,7 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, { case GIMPLE_ASSIGN: /* Try to simplify by copy-propagating the definition. */ - return and_var_with_comparison (op1a, invert, code2, op2a, op2b); + return and_var_with_comparison (op1a, invert, code2, op2a, op2b, gsi); case GIMPLE_PHI: /* If every argument to the PHI produces the same result when @@ -5813,7 +5705,7 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, gimple_bb (stmt))) return NULL_TREE; temp = and_var_with_comparison (arg, invert, code2, - op2a, op2b); + op2a, op2b, gsi); if (!temp) return NULL_TREE; else if (!result) @@ -5845,7 +5737,7 @@ static tree maybe_fold_comparisons_from_match_pd (enum tree_code code, enum tree_code code1, tree op1a, tree op1b, enum tree_code code2, tree op2a, - tree op2b) + tree op2b, gimple_stmt_iterator *gsi) { tree type = TREE_TYPE (op1a); if (TREE_CODE (type) != VECTOR_TYPE) @@ -5912,6 +5804,18 @@ maybe_fold_comparisons_from_match_pd (enum tree_code code, enum tree_code code1, return NULL_TREE; } } + else if (op.code.is_tree_code () + && TREE_CODE_CLASS ((tree_code)op.code) == tcc_comparison) + { + if (gsi) + { + tree r = make_ssa_name (type); + gassign *assign = gimple_build_assign (r, (tree_code)op.code, + op.ops[0], op.ops[1]); + gsi_insert_before (gsi, assign, GSI_SAME_STMT); + return r; + } + } } return NULL_TREE; @@ -5926,16 +5830,18 @@ maybe_fold_comparisons_from_match_pd (enum tree_code code, enum tree_code code1, tree maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { - if (tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b)) + if (tree t = maybe_fold_comparisons_from_match_pd (BIT_AND_EXPR, code1, op1a, + op1b, code2, op2a, op2b, + gsi)) return t; - if (tree t = and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b)) + if (tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b, gsi)) return t; - if (tree t = maybe_fold_comparisons_from_match_pd (BIT_AND_EXPR, code1, op1a, - op1b, code2, op2a, op2b)) + if (tree t = and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b, gsi)) return t; return NULL_TREE; @@ -5948,7 +5854,8 @@ maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, static tree or_var_with_comparison (tree var, bool invert, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree t; gimple *stmt = SSA_NAME_DEF_STMT (var); @@ -5963,9 +5870,9 @@ or_var_with_comparison (tree var, bool invert, if (invert) t = and_var_with_comparison_1 (stmt, invert_tree_comparison (code2, false), - op2a, op2b); + op2a, op2b, gsi); else - t = or_var_with_comparison_1 (stmt, code2, op2a, op2b); + t = or_var_with_comparison_1 (stmt, code2, op2a, op2b, gsi); return canonicalize_bool (t, invert); } @@ -5975,7 +5882,8 @@ or_var_with_comparison (tree var, bool invert, static tree or_var_with_comparison_1 (gimple *stmt, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree var = gimple_assign_lhs (stmt); tree true_test_var = NULL_TREE; @@ -6008,9 +5916,7 @@ or_var_with_comparison_1 (gimple *stmt, tree t = or_comparisons_1 (innercode, gimple_assign_rhs1 (stmt), gimple_assign_rhs2 (stmt), - code2, - op2a, - op2b); + code2, op2a, op2b, gsi); if (t) return t; } @@ -6041,11 +5947,13 @@ or_var_with_comparison_1 (gimple *stmt, else if (inner1 == false_test_var) return (is_or ? boolean_true_node - : or_var_with_comparison (inner2, false, code2, op2a, op2b)); + : or_var_with_comparison (inner2, false, code2, op2a, op2b, + gsi)); else if (inner2 == false_test_var) return (is_or ? boolean_true_node - : or_var_with_comparison (inner1, false, code2, op2a, op2b)); + : or_var_with_comparison (inner1, false, code2, op2a, op2b, + gsi)); /* Next, redistribute/reassociate the OR across the inner tests. Compute the first partial result, (inner1 OR (op2a code op2b)) */ @@ -6055,7 +5963,7 @@ or_var_with_comparison_1 (gimple *stmt, && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), - code2, op2a, op2b))) + code2, op2a, op2b, gsi))) { /* Handle the OR case, where we are reassociating: (inner1 OR inner2) OR (op2a code2 op2b) @@ -6087,7 +5995,7 @@ or_var_with_comparison_1 (gimple *stmt, && (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s), gimple_assign_rhs1 (s), gimple_assign_rhs2 (s), - code2, op2a, op2b))) + code2, op2a, op2b, gsi))) { /* Handle the OR case, where we are reassociating: (inner1 OR inner2) OR (op2a code2 op2b) @@ -6142,7 +6050,8 @@ or_var_with_comparison_1 (gimple *stmt, static tree or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { tree truth_type = truth_type_for (TREE_TYPE (op1a)); @@ -6315,7 +6224,7 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, { case GIMPLE_ASSIGN: /* Try to simplify by copy-propagating the definition. */ - return or_var_with_comparison (op1a, invert, code2, op2a, op2b); + return or_var_with_comparison (op1a, invert, code2, op2a, op2b, gsi); case GIMPLE_PHI: /* If every argument to the PHI produces the same result when @@ -6366,7 +6275,7 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, gimple_bb (stmt))) return NULL_TREE; temp = or_var_with_comparison (arg, invert, code2, - op2a, op2b); + op2a, op2b, gsi); if (!temp) return NULL_TREE; else if (!result) @@ -6396,16 +6305,18 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, tree maybe_fold_or_comparisons (enum tree_code code1, tree op1a, tree op1b, - enum tree_code code2, tree op2a, tree op2b) + enum tree_code code2, tree op2a, tree op2b, + gimple_stmt_iterator *gsi) { - if (tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b)) + if (tree t = maybe_fold_comparisons_from_match_pd (BIT_IOR_EXPR, code1, op1a, + op1b, code2, op2a, op2b, + gsi)) return t; - if (tree t = or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b)) + if (tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b, gsi)) return t; - if (tree t = maybe_fold_comparisons_from_match_pd (BIT_IOR_EXPR, code1, op1a, - op1b, code2, op2a, op2b)) + if (tree t = or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b, gsi)) return t; return NULL_TREE; diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h index 673d484ff52..3c2d19862a0 100644 --- a/gcc/gimple-fold.h +++ b/gcc/gimple-fold.h @@ -32,9 +32,11 @@ extern bool fold_stmt (gimple_stmt_iterator *); extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree)); extern bool fold_stmt_inplace (gimple_stmt_iterator *); extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree, - enum tree_code, tree, tree); + enum tree_code, tree, tree, + gimple_stmt_iterator *gsi); extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree, - enum tree_code, tree, tree); + enum tree_code, tree, tree, + gimple_stmt_iterator *gsi); extern bool optimize_atomic_compare_exchange_p (gimple *); extern void fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *); extern bool arith_overflowed_p (enum tree_code, const_tree, const_tree, diff --git a/gcc/match.pd b/gcc/match.pd index 28512d19b73..2c64c460fda 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1949,6 +1949,74 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (eqne == NE_EXPR) { constant_boolean_node (true, type); }))))) +/* Convert (X == CST1) && (X OP2 CST2) to a known value + based on CST1 OP2 CST2. Similarly for (X != CST1). */ + +(for code1 (eq ne) + (for code2 (eq ne lt gt le ge) + (for and (truth_and bit_and) + (simplify + (and:c (code1 @0 INTEGER_CST@1) (code2 @0 INTEGER_CST@2)) + (with + { + int cmp = tree_int_cst_compare (@1, @2); + bool val; + switch (code2) + { + case EQ_EXPR: val = (cmp == 0); break; + case NE_EXPR: val = (cmp != 0); break; + case LT_EXPR: val = (cmp < 0); break; + case GT_EXPR: val = (cmp > 0); break; + case LE_EXPR: val = (cmp <= 0); break; + case GE_EXPR: val = (cmp >= 0); break; + default: gcc_unreachable (); + } + } + (switch + (if (code1 == EQ_EXPR && val) (code1 @0 @1)) + (if (code1 == EQ_EXPR && !val) { constant_boolean_node (false, type); }) + (if (code1 == NE_EXPR && !val) (code2 @0 @2)))))))) + +/* Convert (X OP1 CST1) && (X OP2 CST2). */ + +(for code1 (lt le gt ge) + (for code2 (lt le gt ge) + (for and (truth_and bit_and) + (simplify + (and (code1:c @0 INTEGER_CST@1) (code2:c @0 INTEGER_CST@2)) + (with + { + int cmp = tree_int_cst_compare (@1, @2); + } + (switch + /* Chose the more restrictive of two < or <= comparisons. */ + (if ((code1 == LT_EXPR || code1 == LE_EXPR) + && (code2 == LT_EXPR || code2 == LE_EXPR)) + (if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR)) + (code1 @0 @1) + (code2 @0 @2))) + /* Likewise chose the more restrictive of two > or >= comparisons. */ + (if ((code1 == GT_EXPR || code1 == GE_EXPR) + && (code2 == GT_EXPR || code2 == GE_EXPR)) + (if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR)) + (code1 @0 @1) + (code2 @0 @2))) + /* Check for singleton ranges. */ + (if (cmp == 0 + && ((code1 == LE_EXPR && code2 == GE_EXPR) + || (code1 == GE_EXPR && code2 == LE_EXPR))) + (eq @0 @1)) + /* Check for disjoint ranges. */ + (if (cmp <= 0 + && (code1 == LT_EXPR || code1 == LE_EXPR) + && (code2 == GT_EXPR || code2 == GE_EXPR)) + { constant_boolean_node (false, type); }) + (if (cmp >= 0 + && (code1 == GT_EXPR || code1 == GE_EXPR) + && (code2 == LT_EXPR || code2 == LE_EXPR)) + { constant_boolean_node (false, type); }) + )))))) + /* We can't reassociate at all for saturating types. */ (if (!TYPE_SATURATING (type)) diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index da67e39e03a..459cba2f752 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -437,7 +437,7 @@ fold_or_predicates (location_t loc, tree c1, tree c2) if (code1 != ERROR_MARK && code2 != ERROR_MARK) { tree t = maybe_fold_or_comparisons (code1, op1a, op1b, - code2, op2a, op2b); + code2, op2a, op2b, NULL); if (t) return t; } diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c index f30816ace7b..92542817604 100644 --- a/gcc/tree-ssa-ifcombine.c +++ b/gcc/tree-ssa-ifcombine.c @@ -555,15 +555,16 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, return false; /* Don't return false so fast, try maybe_fold_or_comparisons? */ + gimple_stmt_iterator gsi = gsi_for_stmt (inner_cond); if (!(t = maybe_fold_and_comparisons (inner_cond_code, gimple_cond_lhs (inner_cond), gimple_cond_rhs (inner_cond), outer_cond_code, gimple_cond_lhs (outer_cond), - gimple_cond_rhs (outer_cond)))) + gimple_cond_rhs (outer_cond), + &gsi))) { tree t1, t2; - gimple_stmt_iterator gsi; bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT; if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1) logical_op_non_short_circuit diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index df76e66bccf..ae0752bb371 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -2091,11 +2091,13 @@ eliminate_redundant_comparison (enum tree_code opcode, if (opcode == BIT_IOR_EXPR) t = maybe_fold_or_comparisons (lcode, op1, op2, rcode, gimple_assign_rhs1 (def2), - gimple_assign_rhs2 (def2)); + gimple_assign_rhs2 (def2), + NULL); else t = maybe_fold_and_comparisons (lcode, op1, op2, rcode, gimple_assign_rhs1 (def2), - gimple_assign_rhs2 (def2)); + gimple_assign_rhs2 (def2), + NULL); if (!t) continue; @@ -3834,9 +3836,10 @@ optimize_vec_cond_expr (tree_code opcode, vec *ops) tree comb; if (opcode == BIT_AND_EXPR) - comb = maybe_fold_and_comparisons (cmp0, x0, y0, cmp1, x1, y1); + comb = maybe_fold_and_comparisons (cmp0, x0, y0, cmp1, x1, y1, + NULL); else if (opcode == BIT_IOR_EXPR) - comb = maybe_fold_or_comparisons (cmp0, x0, y0, cmp1, x1, y1); + comb = maybe_fold_or_comparisons (cmp0, x0, y0, cmp1, x1, y1, NULL); else gcc_unreachable (); if (comb == NULL) -- 2.23.0 From patchwork Mon Sep 9 12:24:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 1159695 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508613-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="sWLYBtJl"; dkim-atps=neutral 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 46RnRh2Gtfz9s7T for ; Mon, 9 Sep 2019 22:25:04 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:from:to:cc:references:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=lRLcdHnGcBbLDJ4iB yvdyXw8JAets3ed5WbMmS25Kkz1+CcaOVf5w9h6q0Ky61khhcnJ8Km+1PYXJPZ45 50JZ0INknWLh+wriq+G8OhdkqN1gftVJSpiAItmCba9IvsmOBulda3OcuxBaRlyx uez6AUVgbcXxMLcXCUTY8wl1/k= 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 :subject:from:to:cc:references:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=nQkPcX/ACC1cFwWrEOtwoRy cC/c=; b=sWLYBtJlFk3X2aJTYrsVKZsujpRSsGPalcpWK0bUXg3u+XZfoNeiR2e HhMQMdTwLcY4l17cYCuj23eCUwOgwXGPrJK4vHwmCz5r8cwtmfbeGvgWb77MGVJL tfmHxd3EPtfbcZ6/gQPetIR6Wa3zuhFWti2UVuqVyryrYCnPo4eM= Received: (qmail 78203 invoked by alias); 9 Sep 2019 12:24:51 -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 73136 invoked by uid 89); 9 Sep 2019 12:24:47 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-17.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 12:24:46 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 0A159AFF1; Mon, 9 Sep 2019 12:24:44 +0000 (UTC) Subject: [PATCH 4/5] Rewrite first part of or_comparisons_1 into match.pd. From: =?utf-8?q?Martin_Li=C5=A1ka?= To: Richard Biener , Li Jia He Cc: Andrew Pinski , Jeff Law , GCC Patches , Segher Boessenkool , wschmidt@linux.ibm.com, Martin Liska References: <1561615913-22109-1-git-send-email-helijia@linux.ibm.com> <6fb28248-5134-cec5-5045-45253e4d2eb0@redhat.com> <6d333ccf-9905-e929-c2dc-fc611ff929f1@linux.ibm.com> <845bc280-7bd6-509b-3830-4ebde50f1b20@linux.ibm.com> Message-ID: <5e5ccdfb-ea7c-a955-75b2-8d947091d897@suse.cz> Date: Mon, 9 Sep 2019 14:24:43 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes Hi. Next part if about transition of part of the OR patterns into match.pd. Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin From 0cc83b72025d243e9e6ebaa9a85c68c17f9cd09a Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Fri, 6 Sep 2019 12:47:01 +0200 Subject: [PATCH 4/5] Rewrite first part of or_comparisons_1 into match.pd. gcc/ChangeLog: 2019-09-09 Martin Liska * gimple-fold.c (or_comparisons_1): Remove rules moved to ... * match.pd: ... here. --- gcc/gimple-fold.c | 87 +---------------------------------------------- gcc/match.pd | 29 ++++++++++++++++ 2 files changed, 30 insertions(+), 86 deletions(-) diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index f9971c004b7..e691780591c 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -6088,93 +6088,8 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, { int cmp = tree_int_cst_compare (op1b, op2b); - /* If we have (op1a != op1b), we should either be able to - return that or TRUE, depending on whether the constant op1b - also satisfies the other comparison against op2b. */ - if (code1 == NE_EXPR) - { - bool done = true; - bool val; - switch (code2) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp < 0); break; - case GT_EXPR: val = (cmp > 0); break; - case LE_EXPR: val = (cmp <= 0); break; - case GE_EXPR: val = (cmp >= 0); break; - default: done = false; - } - if (done) - { - if (val) - return boolean_true_node; - else - return fold_build2 (code1, boolean_type_node, op1a, op1b); - } - } - /* Likewise if the second comparison is a != comparison. */ - else if (code2 == NE_EXPR) - { - bool done = true; - bool val; - switch (code1) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp > 0); break; - case GT_EXPR: val = (cmp < 0); break; - case LE_EXPR: val = (cmp >= 0); break; - case GE_EXPR: val = (cmp <= 0); break; - default: done = false; - } - if (done) - { - if (val) - return boolean_true_node; - else - return fold_build2 (code2, boolean_type_node, op2a, op2b); - } - } - - /* See if an equality test is redundant with the other comparison. */ - else if (code1 == EQ_EXPR) - { - bool val; - switch (code2) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp < 0); break; - case GT_EXPR: val = (cmp > 0); break; - case LE_EXPR: val = (cmp <= 0); break; - case GE_EXPR: val = (cmp >= 0); break; - default: - val = false; - } - if (val) - return fold_build2 (code2, boolean_type_node, op2a, op2b); - } - else if (code2 == EQ_EXPR) - { - bool val; - switch (code1) - { - case EQ_EXPR: val = (cmp == 0); break; - case NE_EXPR: val = (cmp != 0); break; - case LT_EXPR: val = (cmp > 0); break; - case GT_EXPR: val = (cmp < 0); break; - case LE_EXPR: val = (cmp >= 0); break; - case GE_EXPR: val = (cmp <= 0); break; - default: - val = false; - } - if (val) - return fold_build2 (code1, boolean_type_node, op1a, op1b); - } - /* Chose the less restrictive of two < or <= comparisons. */ - else if ((code1 == LT_EXPR || code1 == LE_EXPR) + if ((code1 == LT_EXPR || code1 == LE_EXPR) && (code2 == LT_EXPR || code2 == LE_EXPR)) { if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR)) diff --git a/gcc/match.pd b/gcc/match.pd index 2c64c460fda..2923f5b4cbe 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2017,6 +2017,35 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) { constant_boolean_node (false, type); }) )))))) +/* Convert (X == CST1) || (X OP2 CST2) to a known value + based on CST1 OP2 CST2. Similarly for (X != CST1). */ + +(for code1 (eq ne) + (for code2 (eq ne lt gt le ge) + (for or (truth_or bit_ior) + (simplify + (or:c (code1 @0 INTEGER_CST@1) (code2 @0 INTEGER_CST@2)) + (with + { + int cmp = tree_int_cst_compare (@1, @2); + bool val; + switch (code2) + { + case EQ_EXPR: val = (cmp == 0); break; + case NE_EXPR: val = (cmp != 0); break; + case LT_EXPR: val = (cmp < 0); break; + case GT_EXPR: val = (cmp > 0); break; + case LE_EXPR: val = (cmp <= 0); break; + case GE_EXPR: val = (cmp >= 0); break; + default: gcc_unreachable (); + } + } + (switch + (if (code1 == EQ_EXPR && val) (code2 @0 @2)) + (if (code1 == NE_EXPR && val) { constant_boolean_node (true, type); }) + (if (code1 == NE_EXPR && !val) (code1 @0 @1)))))))) + + /* We can't reassociate at all for saturating types. */ (if (!TYPE_SATURATING (type)) -- 2.23.0 From patchwork Mon Sep 9 12:25:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 1159696 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508614-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="gUJV8KSu"; dkim-atps=neutral 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 46RnRz3CNtz9s7T for ; Mon, 9 Sep 2019 22:25:19 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :subject:from:to:cc:references:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=lg08ELRTpvIUUHAks ZyBd2MPvKGy/ZVHE41nY48NwL2YMtUzKAAurFxeWCzdHbgsXXemTlvahXvDcK7xc 1He2jpMD8ghQVVzQdsb6FqStCSCo3Z1T36QBGmZnd8RF9xxE082qOwGr38r1Vpaw fY0715AZSAe9WsqZ13MI6B5vYM= 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 :subject:from:to:cc:references:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=JhSAuzet02KTyLogIItLBVv d1rM=; b=gUJV8KSuPFVvikmjoV7MFmvAxGbTxd+7GlZ0gXs6g/FR8u/7XEh9CGT jSixje0HhKInF9FdmOqSOOI2xA+H0b6UMDQJuGTVNTRE+Hm16RiLTsGdrw6LZeiu 2KxfTxoZ4M6NobQfDK1OYSGVfD/2JuPwdYBqRInIZTBESXetaItY= Received: (qmail 84436 invoked by alias); 9 Sep 2019 12:25:12 -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 84187 invoked by uid 89); 9 Sep 2019 12:25:12 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-17.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 09 Sep 2019 12:25:11 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id D7252AD29; Mon, 9 Sep 2019 12:25:08 +0000 (UTC) Subject: [PATCH 5/5] Rewrite second part of or_comparisons_1 into match.pd. From: =?utf-8?q?Martin_Li=C5=A1ka?= To: Richard Biener , Li Jia He Cc: Andrew Pinski , Jeff Law , GCC Patches , Segher Boessenkool , wschmidt@linux.ibm.com, Martin Liska References: <1561615913-22109-1-git-send-email-helijia@linux.ibm.com> <6fb28248-5134-cec5-5045-45253e4d2eb0@redhat.com> <6d333ccf-9905-e929-c2dc-fc611ff929f1@linux.ibm.com> <845bc280-7bd6-509b-3830-4ebde50f1b20@linux.ibm.com> Message-ID: <8610940b-71c1-53bd-642a-ba1de5f750ce@suse.cz> Date: Mon, 9 Sep 2019 14:25:08 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes And finally the second part of OR patterns. Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin From 621d25811179bce8a8ad58a88b742528e97917d6 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Fri, 6 Sep 2019 12:59:36 +0200 Subject: [PATCH 5/5] Rewrite second part of or_comparisons_1 into match.pd. gcc/ChangeLog: 2019-09-09 Martin Liska * gimple-fold.c (or_comparisons_1): Remove rules moved to ... * match.pd: ... here. --- gcc/gimple-fold.c | 45 --------------------------------------------- gcc/match.pd | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 45 deletions(-) diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index e691780591c..ac24f3b408b 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -6080,51 +6080,6 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, return t; } - /* If both comparisons are of the same value against constants, we might - be able to merge them. */ - if (operand_equal_p (op1a, op2a, 0) - && TREE_CODE (op1b) == INTEGER_CST - && TREE_CODE (op2b) == INTEGER_CST) - { - int cmp = tree_int_cst_compare (op1b, op2b); - - /* Chose the less restrictive of two < or <= comparisons. */ - if ((code1 == LT_EXPR || code1 == LE_EXPR) - && (code2 == LT_EXPR || code2 == LE_EXPR)) - { - if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR)) - return fold_build2 (code2, boolean_type_node, op2a, op2b); - else - return fold_build2 (code1, boolean_type_node, op1a, op1b); - } - - /* Likewise chose the less restrictive of two > or >= comparisons. */ - else if ((code1 == GT_EXPR || code1 == GE_EXPR) - && (code2 == GT_EXPR || code2 == GE_EXPR)) - { - if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR)) - return fold_build2 (code2, boolean_type_node, op2a, op2b); - else - return fold_build2 (code1, boolean_type_node, op1a, op1b); - } - - /* Check for singleton ranges. */ - else if (cmp == 0 - && ((code1 == LT_EXPR && code2 == GT_EXPR) - || (code1 == GT_EXPR && code2 == LT_EXPR))) - return fold_build2 (NE_EXPR, boolean_type_node, op1a, op2b); - - /* Check for less/greater pairs that don't restrict the range at all. */ - else if (cmp >= 0 - && (code1 == LT_EXPR || code1 == LE_EXPR) - && (code2 == GT_EXPR || code2 == GE_EXPR)) - return boolean_true_node; - else if (cmp <= 0 - && (code1 == GT_EXPR || code1 == GE_EXPR) - && (code2 == LT_EXPR || code2 == LE_EXPR)) - return boolean_true_node; - } - /* Perhaps the first comparison is (NAME != 0) or (NAME == 1) where NAME's definition is a truth value. See if there are any simplifications that can be done against the NAME's definition. */ diff --git a/gcc/match.pd b/gcc/match.pd index 2923f5b4cbe..15916800bc1 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2045,6 +2045,45 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (code1 == NE_EXPR && val) { constant_boolean_node (true, type); }) (if (code1 == NE_EXPR && !val) (code1 @0 @1)))))))) +/* Convert (X OP1 CST1) || (X OP2 CST2). */ + +(for code1 (lt le gt ge) + (for code2 (lt le gt ge) + (for or (truth_or bit_ior) + (simplify + (or (code1:c @0 INTEGER_CST@1) (code2:c @0 INTEGER_CST@2)) + (with + { + int cmp = tree_int_cst_compare (@1, @2); + } + (switch + /* Chose the more restrictive of two < or <= comparisons. */ + (if ((code1 == LT_EXPR || code1 == LE_EXPR) + && (code2 == LT_EXPR || code2 == LE_EXPR)) + (if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR)) + (code2 @0 @2) + (code1 @0 @1))) + /* Likewise chose the more restrictive of two > or >= comparisons. */ + (if ((code1 == GT_EXPR || code1 == GE_EXPR) + && (code2 == GT_EXPR || code2 == GE_EXPR)) + (if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR)) + (code2 @0 @2) + (code1 @0 @1))) + /* Check for singleton ranges. */ + (if (cmp == 0 + && ((code1 == LT_EXPR && code2 == GT_EXPR) + || (code1 == GT_EXPR && code2 == LT_EXPR))) + (ne @0 @2)) + /* Check for disjoint ranges. */ + (if (cmp >= 0 + && (code1 == LT_EXPR || code1 == LE_EXPR) + && (code2 == GT_EXPR || code2 == GE_EXPR)) + { constant_boolean_node (true, type); }) + (if (cmp <= 0 + && (code1 == GT_EXPR || code1 == GE_EXPR) + && (code2 == LT_EXPR || code2 == LE_EXPR)) + { constant_boolean_node (true, type); }) + )))))) /* We can't reassociate at all for saturating types. */ (if (!TYPE_SATURATING (type)) -- 2.23.0