From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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-Archive: List-Post: List-Help: Sender: gcc-patches-owner@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, 06 Sep 2019 10:13:00 -0000 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: Content-Type: multipart/mixed; boundary="------------7D285E51D3BCDB796ACB8E33" X-IsSubscribed: yes X-SW-Source: 2019-09/txt/msg00347.txt.bz2 This is a multi-part message in MIME format. --------------7D285E51D3BCDB796ACB8E33 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Content-length: 3447 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 --------------7D285E51D3BCDB796ACB8E33 Content-Type: text/x-patch; name="0001-Auto-generate-maybe_fold_and-or_comparisons-from-mat.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0001-Auto-generate-maybe_fold_and-or_comparisons-from-mat.pa"; filename*1="tch" Content-length: 10312 >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 --------------7D285E51D3BCDB796ACB8E33--