Commit ae9c3507 by Martin Liska Committed by Martin Liska

Rewrite part of and_comparisons_1 into match.pd.

2019-09-16  Martin Liska  <mliska@suse.cz>

	* genmatch.c (dt_node::append_simplify): Do not print
	warning when we have duplicate patterns belonging
	to a same simplify rule.
	* gimple-fold.c (and_comparisons_1): Remove matching moved to match.pd.
	(maybe_fold_comparisons_from_match_pd): Handle
	tcc_comparison as a results.
	* match.pd: Handle (X == CST1) && (X OP2 CST2) conditions.

From-SVN: r275750
parent c16504f6
2019-09-16 Martin Liska <mliska@suse.cz>
* genmatch.c (dt_node::append_simplify): Do not print
warning when we have duplicate patterns belonging
to a same simplify rule.
* gimple-fold.c (and_comparisons_1): Remove matching moved to match.pd.
(maybe_fold_comparisons_from_match_pd): Handle
tcc_comparison as a results.
* match.pd: Handle (X == CST1) && (X OP2 CST2) conditions.
2019-09-16 Li Jia He <helijia@linux.ibm.com>
Qi Feng <ffengqi@linux.ibm.com>
......
......@@ -1894,10 +1894,15 @@ 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]))
&& (verbose >= 1
|| s->match->location != s2->s->match->location))
{
/* With a nested patters, it's hard to avoid these in order
to keep match.pd rules relatively small. */
warning_at (s->match->location, "duplicate pattern");
warning_at (s2->s->match->location, "previous pattern defined here");
print_operand (s->match, stderr);
......
......@@ -5620,136 +5620,6 @@ and_comparisons_1 (tree type, 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. */
......@@ -5899,6 +5769,16 @@ maybe_fold_comparisons_from_match_pd (tree type, enum tree_code code,
else
return res;
}
else if (op.code.is_tree_code ()
&& TREE_CODE_CLASS ((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);
}
}
return NULL_TREE;
......
......@@ -1958,6 +1958,72 @@ 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)
(simplify
(bit_and:c (code1@3 @0 INTEGER_CST@1) (code2@4 @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) @3)
(if (code1 == EQ_EXPR && !val) { constant_boolean_node (false, type); })
(if (code1 == NE_EXPR && !val) @4))))))
/* Convert (X OP1 CST1) && (X OP2 CST2). */
(for code1 (lt le gt ge)
(for code2 (lt le gt ge)
(simplify
(bit_and (code1:c@3 @0 INTEGER_CST@1) (code2:c@4 @0 INTEGER_CST@2))
(with
{
int cmp = tree_int_cst_compare (@1, @2);
}
(switch
/* Choose 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))
@3
@4))
/* 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))
@3
@4))
/* 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))
......
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