On 9/9/19 3:10 PM, Richard Biener wrote:
> On Mon, 9 Sep 2019, Martin Liška wrote:
>
>> Hi.
>>
>> I'm sending slightly updated version of the patch where we
>> need to properly select type in maybe_fold_comparisons_from_match_pd
>> function for the created SSA_NAMEs. We can be called for a VECTOR_TYPE
>> and so that we can't return a boolean_type_node.
>>
>> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
>>
>> Ready to be installed?
>
> 2019-07-16 Li Jia He <[email protected]>
> Martin Liska <[email protected]>
>
> * 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.
>
> Likewise?
Fixed.
>
> * tree-ssanames.c (init_ssa_name_imm_use): Use make_ssa_name_fn.
> (make_ssa_name_fn): New.
>
> You didn't touch make_ssa_name_fn.
Likewise here.
>
> Since we're needing another iteration:
>
> + /* Allocate gimple stmt1 on the stack. */
> + gimple *stmt1 = (gimple *) XALLOCAVEC (char, gimple_size
> (GIMPLE_ASSIGN, 2));
>
> You can use gassign *stmt1 here so all the gimple_assign_ fns below
> get cheaper.
>
> + 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);
>
> you shouldn't expand SSA names here unless that SSA name is
> exactly lhs1 or lhs2 from above. So
Ah, got it.
>
> if (res == lhs1)
> return build2 (...);
> else if (res == lhs2)
> return build2 (..);
> else
> return res;
>
> plus you miss the case where 'op' became a simplified comparison
> in itself. So,
Yes, that part is included in part 3. I'm going to send the updated patch
3 as well soon.
>
> if (op.code.is_tree_code ()
> && TREE_CODE_CLASS ((enum tree_code)op.code) == tcc_comparison)
> {
> tree op0 = op.ops[0];
> tree op1 = op.ops[1];
> if (op0 == lhs1 || op0 == lhs2 || op1 == lhs1 || op1 == lhs2)
> return NULL_TREE; /* not simple */
> return build2 ((enum tree_code)op.code, op.type,
> op0, op1);
> }
>
> note you need not fold_ again. It's of course ugly that we
> need to build a GENERIC tree here but that's the current interface
> and thus OK at the moment.
I see. But what I need is to insert newly created GIMPLE assignment to
the provided gimple sequence (gsi), right?
Thanks,
Martin
>
> Thanks,
> Richard.
>
>From a0b4daec604ee92ac8e76e416cd912d7d176a811 Mon Sep 17 00:00:00 2001
From: Li Jia He <[email protected]>
Date: Mon, 15 Jul 2019 00:30:25 -0500
Subject: [PATCH 1/5] Auto-generate maybe_fold_and/or_comparisons from match.pd
gcc/ChangeLog
2019-07-16 Li Jia He <[email protected]>
Martin Liska <[email protected]>
* 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): Make it external and add new num_ops argument.
* 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): New.
(make_ssa_name_fn): Use make_ssa_name_fn.
* 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..50cb3bf7e32 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)
+{
+ tree type = TREE_TYPE (op1a);
+ if (TREE_CODE (type) != VECTOR_TYPE)
+ type = boolean_type_node;
+
+ /* 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) = type;
+ 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) = type;
+ 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,
+ type, 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:
+ {
+ if (res == lhs1)
+ return build2 (code1, type, op1a, op1b);
+ else if (res == lhs2)
+ return build2 (code2, type, op2a, op2b);
+ else
+ return res;
+ }
+ 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