Commit 5f487a34 by Li Jia He Committed by Martin Liska

Auto-generate maybe_fold_and/or_comparisons from match.pd

2019-09-16  Li Jia He  <helijia@linux.ibm.com>
	    Martin Liska  <mliska@suse.cz>

	* gimple-fold.c (and_comparisons_1): Add type as first
	argument.
	(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_and_comparisons): Call maybe_fold_comparisons_from_match_pd.
	(maybe_fold_or_comparisons): Likewise.
	(maybe_fold_comparisons_from_match_pd): New.
	* gimple-fold.h (maybe_fold_and_comparisons): Add type argument.
	(maybe_fold_or_comparisons): Likewise.
	* gimple.c (gimple_size): Make it public and add num_ops argument.
	(gimple_init): New function.
	(gimple_alloc): Call gimple_init.
	* gimple.h (gimple_size): New.
	(gimple_init): Likewise.
	* tree-if-conv.c (fold_or_predicates): Pass type.
	* tree-ssa-ifcombine.c (ifcombine_ifandif): Likewise.
	* tree-ssa-reassoc.c (eliminate_redundant_comparison): Likewise.
	(optimize_vec_cond_expr): Likewise.
	(ovce_extract_ops): Return type of conditional expression.
	* tree-ssanames.c (init_ssa_name_imm_use): New.
	(make_ssa_name_fn): Use init_ssa_name_imm_use.
	* tree-ssanames.h (init_ssa_name_imm_use): New.

Co-Authored-By: Martin Liska <mliska@suse.cz>

From-SVN: r275748
parent 10f30ac9
2019-09-16 Li Jia He <helijia@linux.ibm.com>
Martin Liska <mliska@suse.cz>
* gimple-fold.c (and_comparisons_1): Add type as first
argument.
(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_and_comparisons): Call maybe_fold_comparisons_from_match_pd.
(maybe_fold_or_comparisons): Likewise.
(maybe_fold_comparisons_from_match_pd): New.
* gimple-fold.h (maybe_fold_and_comparisons): Add type argument.
(maybe_fold_or_comparisons): Likewise.
* gimple.c (gimple_size): Make it public and add num_ops argument.
(gimple_init): New function.
(gimple_alloc): Call gimple_init.
* gimple.h (gimple_size): New.
(gimple_init): Likewise.
* tree-if-conv.c (fold_or_predicates): Pass type.
* tree-ssa-ifcombine.c (ifcombine_ifandif): Likewise.
* tree-ssa-reassoc.c (eliminate_redundant_comparison): Likewise.
(optimize_vec_cond_expr): Likewise.
(ovce_extract_ops): Return type of conditional expression.
* tree-ssanames.c (init_ssa_name_imm_use): New.
(make_ssa_name_fn): Use init_ssa_name_imm_use.
* tree-ssanames.h (init_ssa_name_imm_use): New.
2019-09-16 Richard Biener <rguenther@suse.de> 2019-09-16 Richard Biener <rguenther@suse.de>
PR tree-optimization/91756 PR tree-optimization/91756
......
...@@ -5371,22 +5371,22 @@ same_bool_result_p (const_tree op1, const_tree op2) ...@@ -5371,22 +5371,22 @@ same_bool_result_p (const_tree op1, const_tree op2)
/* Forward declarations for some mutually recursive functions. */ /* Forward declarations for some mutually recursive functions. */
static tree static tree
and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b); enum tree_code code2, tree op2a, tree op2b);
static tree static tree
and_var_with_comparison (tree var, bool invert, and_var_with_comparison (tree type, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b); enum tree_code code2, tree op2a, tree op2b);
static tree static tree
and_var_with_comparison_1 (gimple *stmt, and_var_with_comparison_1 (tree type, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b); enum tree_code code2, tree op2a, tree op2b);
static tree static tree
or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, or_comparisons_1 (tree, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b); enum tree_code code2, tree op2a, tree op2b);
static tree static tree
or_var_with_comparison (tree var, bool invert, or_var_with_comparison (tree, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b); enum tree_code code2, tree op2a, tree op2b);
static tree static tree
or_var_with_comparison_1 (gimple *stmt, or_var_with_comparison_1 (tree, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b); enum tree_code code2, tree op2a, tree op2b);
/* Helper function for and_comparisons_1: try to simplify the AND of the /* Helper function for and_comparisons_1: try to simplify the AND of the
...@@ -5395,7 +5395,7 @@ or_var_with_comparison_1 (gimple *stmt, ...@@ -5395,7 +5395,7 @@ or_var_with_comparison_1 (gimple *stmt,
Return NULL_EXPR if we can't simplify this to a single expression. */ Return NULL_EXPR if we can't simplify this to a single expression. */
static tree static tree
and_var_with_comparison (tree var, bool invert, and_var_with_comparison (tree type, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b) enum tree_code code2, tree op2a, tree op2b)
{ {
tree t; tree t;
...@@ -5409,11 +5409,11 @@ and_var_with_comparison (tree var, bool invert, ...@@ -5409,11 +5409,11 @@ and_var_with_comparison (tree var, bool invert,
!var AND (op2a code2 op2b) => !(var OR !(op2a code2 op2b)) !var AND (op2a code2 op2b) => !(var OR !(op2a code2 op2b))
Then we only have to consider the simpler non-inverted cases. */ Then we only have to consider the simpler non-inverted cases. */
if (invert) if (invert)
t = or_var_with_comparison_1 (stmt, t = or_var_with_comparison_1 (type, stmt,
invert_tree_comparison (code2, false), invert_tree_comparison (code2, false),
op2a, op2b); op2a, op2b);
else else
t = and_var_with_comparison_1 (stmt, code2, op2a, op2b); t = and_var_with_comparison_1 (type, stmt, code2, op2a, op2b);
return canonicalize_bool (t, invert); return canonicalize_bool (t, invert);
} }
...@@ -5422,7 +5422,7 @@ and_var_with_comparison (tree var, bool invert, ...@@ -5422,7 +5422,7 @@ and_var_with_comparison (tree var, bool invert,
Return NULL_EXPR if we can't simplify this to a single expression. */ Return NULL_EXPR if we can't simplify this to a single expression. */
static tree static tree
and_var_with_comparison_1 (gimple *stmt, and_var_with_comparison_1 (tree type, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b) enum tree_code code2, tree op2a, tree op2b)
{ {
tree var = gimple_assign_lhs (stmt); tree var = gimple_assign_lhs (stmt);
...@@ -5453,7 +5453,7 @@ and_var_with_comparison_1 (gimple *stmt, ...@@ -5453,7 +5453,7 @@ and_var_with_comparison_1 (gimple *stmt,
/* If the definition is a comparison, recurse on it. */ /* If the definition is a comparison, recurse on it. */
if (TREE_CODE_CLASS (innercode) == tcc_comparison) if (TREE_CODE_CLASS (innercode) == tcc_comparison)
{ {
tree t = and_comparisons_1 (innercode, tree t = and_comparisons_1 (type, innercode,
gimple_assign_rhs1 (stmt), gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt), gimple_assign_rhs2 (stmt),
code2, code2,
...@@ -5489,18 +5489,20 @@ and_var_with_comparison_1 (gimple *stmt, ...@@ -5489,18 +5489,20 @@ and_var_with_comparison_1 (gimple *stmt,
else if (inner1 == false_test_var) else if (inner1 == false_test_var)
return (is_and return (is_and
? boolean_false_node ? boolean_false_node
: and_var_with_comparison (inner2, false, code2, op2a, op2b)); : and_var_with_comparison (type, inner2, false, code2, op2a,
op2b));
else if (inner2 == false_test_var) else if (inner2 == false_test_var)
return (is_and return (is_and
? boolean_false_node ? boolean_false_node
: and_var_with_comparison (inner1, false, code2, op2a, op2b)); : and_var_with_comparison (type, inner1, false, code2, op2a,
op2b));
/* Next, redistribute/reassociate the AND across the inner tests. /* Next, redistribute/reassociate the AND across the inner tests.
Compute the first partial result, (inner1 AND (op2a code op2b)) */ Compute the first partial result, (inner1 AND (op2a code op2b)) */
if (TREE_CODE (inner1) == SSA_NAME if (TREE_CODE (inner1) == SSA_NAME
&& is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1)) && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1))
&& TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
&& (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s), && (t = maybe_fold_and_comparisons (type, gimple_assign_rhs_code (s),
gimple_assign_rhs1 (s), gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s), gimple_assign_rhs2 (s),
code2, op2a, op2b))) code2, op2a, op2b)))
...@@ -5532,7 +5534,7 @@ and_var_with_comparison_1 (gimple *stmt, ...@@ -5532,7 +5534,7 @@ and_var_with_comparison_1 (gimple *stmt,
if (TREE_CODE (inner2) == SSA_NAME if (TREE_CODE (inner2) == SSA_NAME
&& is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2)) && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2))
&& TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
&& (t = maybe_fold_and_comparisons (gimple_assign_rhs_code (s), && (t = maybe_fold_and_comparisons (type, gimple_assign_rhs_code (s),
gimple_assign_rhs1 (s), gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s), gimple_assign_rhs2 (s),
code2, op2a, op2b))) code2, op2a, op2b)))
...@@ -5588,7 +5590,7 @@ and_var_with_comparison_1 (gimple *stmt, ...@@ -5588,7 +5590,7 @@ and_var_with_comparison_1 (gimple *stmt,
in the first comparison but not the second. */ in the first comparison but not the second. */
static tree static tree
and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b) enum tree_code code2, tree op2a, tree op2b)
{ {
tree truth_type = truth_type_for (TREE_TYPE (op1a)); tree truth_type = truth_type_for (TREE_TYPE (op1a));
...@@ -5762,7 +5764,8 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, ...@@ -5762,7 +5764,8 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
{ {
case GIMPLE_ASSIGN: case GIMPLE_ASSIGN:
/* Try to simplify by copy-propagating the definition. */ /* Try to simplify by copy-propagating the definition. */
return and_var_with_comparison (op1a, invert, code2, op2a, op2b); return and_var_with_comparison (type, op1a, invert, code2, op2a,
op2b);
case GIMPLE_PHI: case GIMPLE_PHI:
/* If every argument to the PHI produces the same result when /* If every argument to the PHI produces the same result when
...@@ -5812,7 +5815,7 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, ...@@ -5812,7 +5815,7 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
gimple_bb (def_stmt), gimple_bb (def_stmt),
gimple_bb (stmt))) gimple_bb (stmt)))
return NULL_TREE; return NULL_TREE;
temp = and_var_with_comparison (arg, invert, code2, temp = and_var_with_comparison (type, arg, invert, code2,
op2a, op2b); op2a, op2b);
if (!temp) if (!temp)
return NULL_TREE; return NULL_TREE;
...@@ -5834,6 +5837,73 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, ...@@ -5834,6 +5837,73 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
return NULL_TREE; 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 (tree type, 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. */
gassign *stmt1
= (gassign *) XALLOCAVEC (char, gimple_size (GIMPLE_ASSIGN, 3));
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. */
gassign *stmt2
= (gassign *) XALLOCAVEC (char, gimple_size (GIMPLE_ASSIGN, 3));
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];
if (res == lhs1)
return build2 (code1, type, op1a, op1b);
else if (res == lhs2)
return build2 (code2, type, op2a, op2b);
else
return res;
}
}
return NULL_TREE;
}
/* Try to simplify the AND of two comparisons, specified by /* Try to simplify the AND of two comparisons, specified by
(OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively. (OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively.
If this can be simplified to a single expression (without requiring If this can be simplified to a single expression (without requiring
...@@ -5842,14 +5912,22 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, ...@@ -5842,14 +5912,22 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
If the result expression is non-null, it has boolean type. */ If the result expression is non-null, it has boolean type. */
tree tree
maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, maybe_fold_and_comparisons (tree type,
enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b) enum tree_code code2, tree op2a, tree op2b)
{ {
tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b); if (tree t = and_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b))
if (t)
return t; return t;
else
return and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b); if (tree t = and_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b))
return t;
if (tree t = maybe_fold_comparisons_from_match_pd (type, 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 /* Helper function for or_comparisons_1: try to simplify the OR of the
...@@ -5858,7 +5936,7 @@ maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b, ...@@ -5858,7 +5936,7 @@ maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b,
Return NULL_EXPR if we can't simplify this to a single expression. */ Return NULL_EXPR if we can't simplify this to a single expression. */
static tree static tree
or_var_with_comparison (tree var, bool invert, or_var_with_comparison (tree type, tree var, bool invert,
enum tree_code code2, tree op2a, tree op2b) enum tree_code code2, tree op2a, tree op2b)
{ {
tree t; tree t;
...@@ -5872,11 +5950,11 @@ or_var_with_comparison (tree var, bool invert, ...@@ -5872,11 +5950,11 @@ or_var_with_comparison (tree var, bool invert,
!var OR (op2a code2 op2b) => !(var AND !(op2a code2 op2b)) !var OR (op2a code2 op2b) => !(var AND !(op2a code2 op2b))
Then we only have to consider the simpler non-inverted cases. */ Then we only have to consider the simpler non-inverted cases. */
if (invert) if (invert)
t = and_var_with_comparison_1 (stmt, t = and_var_with_comparison_1 (type, stmt,
invert_tree_comparison (code2, false), invert_tree_comparison (code2, false),
op2a, op2b); op2a, op2b);
else else
t = or_var_with_comparison_1 (stmt, code2, op2a, op2b); t = or_var_with_comparison_1 (type, stmt, code2, op2a, op2b);
return canonicalize_bool (t, invert); return canonicalize_bool (t, invert);
} }
...@@ -5885,7 +5963,7 @@ or_var_with_comparison (tree var, bool invert, ...@@ -5885,7 +5963,7 @@ or_var_with_comparison (tree var, bool invert,
Return NULL_EXPR if we can't simplify this to a single expression. */ Return NULL_EXPR if we can't simplify this to a single expression. */
static tree static tree
or_var_with_comparison_1 (gimple *stmt, or_var_with_comparison_1 (tree type, gimple *stmt,
enum tree_code code2, tree op2a, tree op2b) enum tree_code code2, tree op2a, tree op2b)
{ {
tree var = gimple_assign_lhs (stmt); tree var = gimple_assign_lhs (stmt);
...@@ -5916,7 +5994,7 @@ or_var_with_comparison_1 (gimple *stmt, ...@@ -5916,7 +5994,7 @@ or_var_with_comparison_1 (gimple *stmt,
/* If the definition is a comparison, recurse on it. */ /* If the definition is a comparison, recurse on it. */
if (TREE_CODE_CLASS (innercode) == tcc_comparison) if (TREE_CODE_CLASS (innercode) == tcc_comparison)
{ {
tree t = or_comparisons_1 (innercode, tree t = or_comparisons_1 (type, innercode,
gimple_assign_rhs1 (stmt), gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt), gimple_assign_rhs2 (stmt),
code2, code2,
...@@ -5952,18 +6030,20 @@ or_var_with_comparison_1 (gimple *stmt, ...@@ -5952,18 +6030,20 @@ or_var_with_comparison_1 (gimple *stmt,
else if (inner1 == false_test_var) else if (inner1 == false_test_var)
return (is_or return (is_or
? boolean_true_node ? boolean_true_node
: or_var_with_comparison (inner2, false, code2, op2a, op2b)); : or_var_with_comparison (type, inner2, false, code2, op2a,
op2b));
else if (inner2 == false_test_var) else if (inner2 == false_test_var)
return (is_or return (is_or
? boolean_true_node ? boolean_true_node
: or_var_with_comparison (inner1, false, code2, op2a, op2b)); : or_var_with_comparison (type, inner1, false, code2, op2a,
op2b));
/* Next, redistribute/reassociate the OR across the inner tests. /* Next, redistribute/reassociate the OR across the inner tests.
Compute the first partial result, (inner1 OR (op2a code op2b)) */ Compute the first partial result, (inner1 OR (op2a code op2b)) */
if (TREE_CODE (inner1) == SSA_NAME if (TREE_CODE (inner1) == SSA_NAME
&& is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1)) && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner1))
&& TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
&& (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s), && (t = maybe_fold_or_comparisons (type, gimple_assign_rhs_code (s),
gimple_assign_rhs1 (s), gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s), gimple_assign_rhs2 (s),
code2, op2a, op2b))) code2, op2a, op2b)))
...@@ -5995,7 +6075,7 @@ or_var_with_comparison_1 (gimple *stmt, ...@@ -5995,7 +6075,7 @@ or_var_with_comparison_1 (gimple *stmt,
if (TREE_CODE (inner2) == SSA_NAME if (TREE_CODE (inner2) == SSA_NAME
&& is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2)) && is_gimple_assign (s = SSA_NAME_DEF_STMT (inner2))
&& TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison && TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison
&& (t = maybe_fold_or_comparisons (gimple_assign_rhs_code (s), && (t = maybe_fold_or_comparisons (type, gimple_assign_rhs_code (s),
gimple_assign_rhs1 (s), gimple_assign_rhs1 (s),
gimple_assign_rhs2 (s), gimple_assign_rhs2 (s),
code2, op2a, op2b))) code2, op2a, op2b)))
...@@ -6052,7 +6132,7 @@ or_var_with_comparison_1 (gimple *stmt, ...@@ -6052,7 +6132,7 @@ or_var_with_comparison_1 (gimple *stmt,
in the first comparison but not the second. */ in the first comparison but not the second. */
static tree static tree
or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, or_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b) enum tree_code code2, tree op2a, tree op2b)
{ {
tree truth_type = truth_type_for (TREE_TYPE (op1a)); tree truth_type = truth_type_for (TREE_TYPE (op1a));
...@@ -6226,7 +6306,8 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, ...@@ -6226,7 +6306,8 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
{ {
case GIMPLE_ASSIGN: case GIMPLE_ASSIGN:
/* Try to simplify by copy-propagating the definition. */ /* Try to simplify by copy-propagating the definition. */
return or_var_with_comparison (op1a, invert, code2, op2a, op2b); return or_var_with_comparison (type, op1a, invert, code2, op2a,
op2b);
case GIMPLE_PHI: case GIMPLE_PHI:
/* If every argument to the PHI produces the same result when /* If every argument to the PHI produces the same result when
...@@ -6276,7 +6357,7 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, ...@@ -6276,7 +6357,7 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
gimple_bb (def_stmt), gimple_bb (def_stmt),
gimple_bb (stmt))) gimple_bb (stmt)))
return NULL_TREE; return NULL_TREE;
temp = or_var_with_comparison (arg, invert, code2, temp = or_var_with_comparison (type, arg, invert, code2,
op2a, op2b); op2a, op2b);
if (!temp) if (!temp)
return NULL_TREE; return NULL_TREE;
...@@ -6306,16 +6387,23 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b, ...@@ -6306,16 +6387,23 @@ or_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
If the result expression is non-null, it has boolean type. */ If the result expression is non-null, it has boolean type. */
tree tree
maybe_fold_or_comparisons (enum tree_code code1, tree op1a, tree op1b, maybe_fold_or_comparisons (tree type,
enum tree_code code1, tree op1a, tree op1b,
enum tree_code code2, tree op2a, tree op2b) enum tree_code code2, tree op2a, tree op2b)
{ {
tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b); if (tree t = or_comparisons_1 (type, code1, op1a, op1b, code2, op2a, op2b))
if (t)
return t; return t;
else
return or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
}
if (tree t = or_comparisons_1 (type, code2, op2a, op2b, code1, op1a, op1b))
return t;
if (tree t = maybe_fold_comparisons_from_match_pd (type, 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. /* Fold STMT to a constant using VALUEIZE to valueize SSA names.
......
...@@ -31,9 +31,9 @@ extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree); ...@@ -31,9 +31,9 @@ extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
extern bool fold_stmt (gimple_stmt_iterator *); extern bool fold_stmt (gimple_stmt_iterator *);
extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree)); extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree));
extern bool fold_stmt_inplace (gimple_stmt_iterator *); extern bool fold_stmt_inplace (gimple_stmt_iterator *);
extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree, extern tree maybe_fold_and_comparisons (tree, enum tree_code, tree, tree,
enum tree_code, tree, tree); enum tree_code, tree, tree);
extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree, extern tree maybe_fold_or_comparisons (tree, enum tree_code, tree, tree,
enum tree_code, tree, tree); enum tree_code, tree, tree);
extern bool optimize_atomic_compare_exchange_p (gimple *); extern bool optimize_atomic_compare_exchange_p (gimple *);
extern void fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *); extern void fold_builtin_atomic_compare_exchange (gimple_stmt_iterator *);
......
...@@ -110,10 +110,27 @@ gimple_set_code (gimple *g, enum gimple_code code) ...@@ -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 /* Return the number of bytes needed to hold a GIMPLE statement with
code CODE. */ code CODE. */
static inline size_t size_t
gimple_size (enum gimple_code code) 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 /* 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) ...@@ -125,10 +142,7 @@ gimple_alloc (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
size_t size; size_t size;
gimple *stmt; gimple *stmt;
size = gimple_size (code); size = gimple_size (code, num_ops);
if (num_ops > 0)
size += sizeof (tree) * (num_ops - 1);
if (GATHER_STATISTICS) if (GATHER_STATISTICS)
{ {
enum gimple_alloc_kind kind = gimple_alloc_kind (code); 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) ...@@ -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); stmt = ggc_alloc_cleared_gimple_statement_stat (size PASS_MEM_STAT);
gimple_set_code (stmt, code); gimple_init (stmt, code, num_ops);
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);
return stmt; return stmt;
} }
......
...@@ -1445,6 +1445,8 @@ extern enum gimple_statement_structure_enum const gss_for_code_[]; ...@@ -1445,6 +1445,8 @@ extern enum gimple_statement_structure_enum const gss_for_code_[];
of comminucating the profile info to the builtin expanders. */ of comminucating the profile info to the builtin expanders. */
extern gimple *currently_expanding_gimple_stmt; 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); gimple *gimple_alloc (enum gimple_code, unsigned CXX_MEM_STAT_INFO);
greturn *gimple_build_return (tree); greturn *gimple_build_return (tree);
void gimple_call_reset_alias_info (gcall *); void gimple_call_reset_alias_info (gcall *);
......
...@@ -436,7 +436,7 @@ fold_or_predicates (location_t loc, tree c1, tree c2) ...@@ -436,7 +436,7 @@ fold_or_predicates (location_t loc, tree c1, tree c2)
if (code1 != ERROR_MARK && code2 != ERROR_MARK) if (code1 != ERROR_MARK && code2 != ERROR_MARK)
{ {
tree t = maybe_fold_or_comparisons (code1, op1a, op1b, tree t = maybe_fold_or_comparisons (boolean_type_node, code1, op1a, op1b,
code2, op2a, op2b); code2, op2a, op2b);
if (t) if (t)
return t; return t;
......
...@@ -555,7 +555,7 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, ...@@ -555,7 +555,7 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
return false; return false;
/* Don't return false so fast, try maybe_fold_or_comparisons? */ /* Don't return false so fast, try maybe_fold_or_comparisons? */
if (!(t = maybe_fold_and_comparisons (inner_cond_code, if (!(t = maybe_fold_and_comparisons (boolean_type_node, inner_cond_code,
gimple_cond_lhs (inner_cond), gimple_cond_lhs (inner_cond),
gimple_cond_rhs (inner_cond), gimple_cond_rhs (inner_cond),
outer_cond_code, outer_cond_code,
......
...@@ -2088,12 +2088,15 @@ eliminate_redundant_comparison (enum tree_code opcode, ...@@ -2088,12 +2088,15 @@ eliminate_redundant_comparison (enum tree_code opcode,
/* If we got here, we have a match. See if we can combine the /* If we got here, we have a match. See if we can combine the
two comparisons. */ two comparisons. */
tree type = TREE_TYPE (gimple_assign_lhs (def1));
if (opcode == BIT_IOR_EXPR) if (opcode == BIT_IOR_EXPR)
t = maybe_fold_or_comparisons (lcode, op1, op2, t = maybe_fold_or_comparisons (type,
lcode, op1, op2,
rcode, gimple_assign_rhs1 (def2), rcode, gimple_assign_rhs1 (def2),
gimple_assign_rhs2 (def2)); gimple_assign_rhs2 (def2));
else else
t = maybe_fold_and_comparisons (lcode, op1, op2, t = maybe_fold_and_comparisons (type,
lcode, op1, op2,
rcode, gimple_assign_rhs1 (def2), rcode, gimple_assign_rhs1 (def2),
gimple_assign_rhs2 (def2)); gimple_assign_rhs2 (def2));
if (!t) if (!t)
...@@ -3745,10 +3748,11 @@ optimize_range_tests (enum tree_code opcode, ...@@ -3745,10 +3748,11 @@ optimize_range_tests (enum tree_code opcode,
/* A subroutine of optimize_vec_cond_expr to extract and canonicalize /* A subroutine of optimize_vec_cond_expr to extract and canonicalize
the operands of the VEC_COND_EXPR. Returns ERROR_MARK on failure, the operands of the VEC_COND_EXPR. Returns ERROR_MARK on failure,
otherwise the comparison code. */ otherwise the comparison code. TYPE is a return value that is set
to type of comparison. */
static tree_code static tree_code
ovce_extract_ops (tree var, gassign **rets, bool *reti) ovce_extract_ops (tree var, gassign **rets, bool *reti, tree *type)
{ {
if (TREE_CODE (var) != SSA_NAME) if (TREE_CODE (var) != SSA_NAME)
return ERROR_MARK; return ERROR_MARK;
...@@ -3790,6 +3794,8 @@ ovce_extract_ops (tree var, gassign **rets, bool *reti) ...@@ -3790,6 +3794,8 @@ ovce_extract_ops (tree var, gassign **rets, bool *reti)
*rets = stmt; *rets = stmt;
if (reti) if (reti)
*reti = inv; *reti = inv;
if (type)
*type = TREE_TYPE (cond);
return cmp; return cmp;
} }
...@@ -3811,7 +3817,8 @@ optimize_vec_cond_expr (tree_code opcode, vec<operand_entry *> *ops) ...@@ -3811,7 +3817,8 @@ optimize_vec_cond_expr (tree_code opcode, vec<operand_entry *> *ops)
gassign *stmt0; gassign *stmt0;
bool invert; bool invert;
tree_code cmp0 = ovce_extract_ops (elt0, &stmt0, &invert); tree type;
tree_code cmp0 = ovce_extract_ops (elt0, &stmt0, &invert, &type);
if (cmp0 == ERROR_MARK) if (cmp0 == ERROR_MARK)
continue; continue;
...@@ -3820,7 +3827,7 @@ optimize_vec_cond_expr (tree_code opcode, vec<operand_entry *> *ops) ...@@ -3820,7 +3827,7 @@ optimize_vec_cond_expr (tree_code opcode, vec<operand_entry *> *ops)
tree &elt1 = (*ops)[j]->op; tree &elt1 = (*ops)[j]->op;
gassign *stmt1; gassign *stmt1;
tree_code cmp1 = ovce_extract_ops (elt1, &stmt1, NULL); tree_code cmp1 = ovce_extract_ops (elt1, &stmt1, NULL, NULL);
if (cmp1 == ERROR_MARK) if (cmp1 == ERROR_MARK)
continue; continue;
...@@ -3834,9 +3841,11 @@ optimize_vec_cond_expr (tree_code opcode, vec<operand_entry *> *ops) ...@@ -3834,9 +3841,11 @@ optimize_vec_cond_expr (tree_code opcode, vec<operand_entry *> *ops)
tree comb; tree comb;
if (opcode == BIT_AND_EXPR) if (opcode == BIT_AND_EXPR)
comb = maybe_fold_and_comparisons (cmp0, x0, y0, cmp1, x1, y1); comb = maybe_fold_and_comparisons (type, cmp0, x0, y0, cmp1, x1,
y1);
else if (opcode == BIT_IOR_EXPR) else if (opcode == BIT_IOR_EXPR)
comb = maybe_fold_or_comparisons (cmp0, x0, y0, cmp1, x1, y1); comb = maybe_fold_or_comparisons (type, cmp0, x0, y0, cmp1, x1,
y1);
else else
gcc_unreachable (); gcc_unreachable ();
if (comb == NULL) if (comb == NULL)
......
...@@ -252,6 +252,19 @@ flush_ssaname_freelist (void) ...@@ -252,6 +252,19 @@ flush_ssaname_freelist (void)
vec_safe_truncate (FREE_SSANAMES_QUEUE (cfun), 0); 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 /* Return an SSA_NAME node for variable VAR defined in statement STMT
in function FN. STMT may be an empty statement for artificial in function FN. STMT may be an empty statement for artificial
references (e.g., default definitions created when a variable is 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, ...@@ -263,8 +276,6 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
unsigned int version) unsigned int version)
{ {
tree t; tree t;
use_operand_p imm;
gcc_assert (VAR_P (var) gcc_assert (VAR_P (var)
|| TREE_CODE (var) == PARM_DECL || TREE_CODE (var) == PARM_DECL
|| TREE_CODE (var) == RESULT_DECL || TREE_CODE (var) == RESULT_DECL
...@@ -318,11 +329,7 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt, ...@@ -318,11 +329,7 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt,
SSA_NAME_IN_FREE_LIST (t) = 0; SSA_NAME_IN_FREE_LIST (t) = 0;
SSA_NAME_IS_DEFAULT_DEF (t) = 0; SSA_NAME_IS_DEFAULT_DEF (t) = 0;
imm = &(SSA_NAME_IMM_USE_NODE (t)); init_ssa_name_imm_use (t);
imm->use = NULL;
imm->prev = imm;
imm->next = imm;
imm->loc.ssa_name = t;
return t; return t;
} }
......
...@@ -82,6 +82,7 @@ extern void fini_ssanames (struct function *); ...@@ -82,6 +82,7 @@ extern void fini_ssanames (struct function *);
extern void ssanames_print_statistics (void); extern void ssanames_print_statistics (void);
extern tree make_ssa_name_fn (struct function *, tree, gimple *, extern tree make_ssa_name_fn (struct function *, tree, gimple *,
unsigned int version = 0); unsigned int version = 0);
extern void init_ssa_name_imm_use (tree);
extern void release_ssa_name_fn (struct function *, tree); extern void release_ssa_name_fn (struct function *, tree);
extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *, extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *,
unsigned int *); unsigned int *);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment