This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 3/5] Rewrite part of and_comparisons_1 into match.pd.
- From: Martin Liška <mliska at suse dot cz>
- To: Richard Biener <rguenther at suse dot de>, Li Jia He <helijia at linux dot ibm dot com>
- Cc: Andrew Pinski <pinskia at gmail dot com>, Jeff Law <law at redhat dot com>, GCC Patches <gcc-patches at gcc dot gnu dot org>, Segher Boessenkool <segher at kernel dot crashing dot org>, wschmidt at linux dot ibm dot com, Martin Liska <mliska at suse dot de>
- Date: Mon, 9 Sep 2019 14:24:01 +0200
- Subject: [PATCH 3/5] Rewrite part of and_comparisons_1 into match.pd.
- 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> <CA+=Sn1mgUXkEBQTzp5Nv5gcANtpZeutisEtQbez_L7xgg39ppw@mail.gmail.com> <alpine.LSU.2.20.1907010920230.10704@zhemvz.fhfr.qr> <bc69c05f-d966-cab7-b79f-a188523f9258@linux.ibm.com> <alpine.LSU.2.20.1907021007050.2976@zhemvz.fhfr.qr> <alpine.LSU.2.20.1907021031040.2976@zhemvz.fhfr.qr> <845bc280-7bd6-509b-3830-4ebde50f1b20@linux.ibm.com> <nycvar.YFH.7.76.1909051446520.5566@zhemvz.fhfr.qr> <daa3c217-3bfc-086d-da27-175a63da2c59@suse.cz>
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 <mliska@suse.cz>
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 <mliska@suse.cz>
* 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 <dt_simplify *> (kids[i]))
+ if ((s2 = dyn_cast <dt_simplify *> (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<operand_entry *> *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