From: Marc Glisse <marc.glisse@inria.fr>
To: gcc-patches@gcc.gnu.org
Subject: Move ABS detection from fold-const.c to match.pd
Date: Sun, 24 May 2015 12:50:00 -0000 [thread overview]
Message-ID: <alpine.DEB.2.02.1505231828530.22033@stedding.saclay.inria.fr> (raw)
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1749 bytes --]
Hello,
I don't think this pattern is done in the branch. Here I am trying to
match what is done in fold-const, but the idea is that we can later add an
extra block where we replace (cmp (minus @2 @3) zerop) with (cmp @2 @3),
maybe with some adjustments ("convert?" all over the place), to help with
PR 64450 / PR 61734.
I didn't exactly match the code in fold-const.c, among other things
because I didn't feel like calling operand_equal_for_comparison_p, and
strip_nops can translate to quite heavy patterns. Except for a few
irrelevant cases (where I simplify more), this seems to generate the same
.original dumps in the cases I tried. But I am not claiming this is the
best way to arrange that code, better ideas are welcome.
I don't understand the old code handling unsigned, but I couldn't find a
case where the new code (doing nothing special for unsigned) generated a
different .original dump. The last pattern had a strange mix of requiring
integer_zerop and talking about signed zero and NaN, I didn't try to
preserve that. The change to genmatch is for zerop, which doesn't try to
valueize anything.
I had a few issues with the machinery. First, genmatch was generating
a switch with duplicate cases (miraculously, replacing 'cond' with an
iteration on 'cnd' worked around it). Second, (plus @0 (negate@0 @1)) is
treated as (plus @0 @0), the pattern on the second occurence of the
capture is silently ignored.
Regtested on ppc64le-redhat-linux.
2015-05-25 Marc Glisse <marc.glisse@inria.fr>
* genmatch.c (write_predicate): Add ATTRIBUTE_UNUSED.
* match.pd (A op 0 ? A : -A, A op 0 ? A : 0): New simplifications.
* fold-const.c (fold_cond_expr_with_comparison): Remove
corresponding code.
--
Marc Glisse
[-- Attachment #2: Type: TEXT/PLAIN, Size: 9816 bytes --]
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c (revision 223630)
+++ gcc/fold-const.c (working copy)
@@ -4875,112 +4875,25 @@ merge_ranges (int *pin_p, tree *plow, tr
Return a folded expression whose code is not a COND_EXPR
anymore, or NULL_TREE if no folding opportunity is found. */
static tree
fold_cond_expr_with_comparison (location_t loc, tree type,
tree arg0, tree arg1, tree arg2)
{
enum tree_code comp_code = TREE_CODE (arg0);
tree arg00 = TREE_OPERAND (arg0, 0);
tree arg01 = TREE_OPERAND (arg0, 1);
- tree arg1_type = TREE_TYPE (arg1);
tree tem;
STRIP_NOPS (arg1);
STRIP_NOPS (arg2);
- /* If we have A op 0 ? A : -A, consider applying the following
- transformations:
-
- A == 0? A : -A same as -A
- A != 0? A : -A same as A
- A >= 0? A : -A same as abs (A)
- A > 0? A : -A same as abs (A)
- A <= 0? A : -A same as -abs (A)
- A < 0? A : -A same as -abs (A)
-
- None of these transformations work for modes with signed
- zeros. If A is +/-0, the first two transformations will
- change the sign of the result (from +0 to -0, or vice
- versa). The last four will fix the sign of the result,
- even though the original expressions could be positive or
- negative, depending on the sign of A.
-
- Note that all these transformations are correct if A is
- NaN, since the two alternatives (A and -A) are also NaNs. */
- if (!HONOR_SIGNED_ZEROS (element_mode (type))
- && (FLOAT_TYPE_P (TREE_TYPE (arg01))
- ? real_zerop (arg01)
- : integer_zerop (arg01))
- && ((TREE_CODE (arg2) == NEGATE_EXPR
- && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
- /* In the case that A is of the form X-Y, '-A' (arg2) may
- have already been folded to Y-X, check for that. */
- || (TREE_CODE (arg1) == MINUS_EXPR
- && TREE_CODE (arg2) == MINUS_EXPR
- && operand_equal_p (TREE_OPERAND (arg1, 0),
- TREE_OPERAND (arg2, 1), 0)
- && operand_equal_p (TREE_OPERAND (arg1, 1),
- TREE_OPERAND (arg2, 0), 0))))
- switch (comp_code)
- {
- case EQ_EXPR:
- case UNEQ_EXPR:
- tem = fold_convert_loc (loc, arg1_type, arg1);
- return pedantic_non_lvalue_loc (loc,
- fold_convert_loc (loc, type,
- negate_expr (tem)));
- case NE_EXPR:
- case LTGT_EXPR:
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
- case UNGE_EXPR:
- case UNGT_EXPR:
- if (flag_trapping_math)
- break;
- /* Fall through. */
- case GE_EXPR:
- case GT_EXPR:
- if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = fold_convert_loc (loc, signed_type_for
- (TREE_TYPE (arg1)), arg1);
- tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
- case UNLE_EXPR:
- case UNLT_EXPR:
- if (flag_trapping_math)
- break;
- case LE_EXPR:
- case LT_EXPR:
- if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = fold_convert_loc (loc, signed_type_for
- (TREE_TYPE (arg1)), arg1);
- tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
- return negate_expr (fold_convert_loc (loc, type, tem));
- default:
- gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
- break;
- }
-
- /* A != 0 ? A : 0 is simply A, unless A is -0. Likewise
- A == 0 ? A : 0 is always 0 unless A is -0. Note that
- both transformations are correct when A is NaN: A != 0
- is then true, and A == 0 is false. */
-
- if (!HONOR_SIGNED_ZEROS (element_mode (type))
- && integer_zerop (arg01) && integer_zerop (arg2))
- {
- if (comp_code == NE_EXPR)
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
- else if (comp_code == EQ_EXPR)
- return build_zero_cst (type);
- }
-
/* Try some transformations of A op B ? A : B.
A == B? A : B same as B
A != B? A : B same as A
A >= B? A : B same as max (A, B)
A > B? A : B same as max (B, A)
A <= B? A : B same as min (A, B)
A < B? A : B same as min (B, A)
As above, these transformations don't work in the presence
Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c (revision 223630)
+++ gcc/genmatch.c (working copy)
@@ -2657,21 +2657,21 @@ decision_tree::gen_generic (FILE *f)
/* Output code to implement the predicate P from the decision tree DT. */
void
write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
{
fprintf (f, "\nbool\n"
"%s%s (tree t%s%s)\n"
"{\n", gimple ? "gimple_" : "tree_", p->id,
p->nargs > 0 ? ", tree *res_ops" : "",
- gimple ? ", tree (*valueize)(tree)" : "");
+ gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : "");
/* Conveniently make 'type' available. */
fprintf (f, "tree type = TREE_TYPE (t);\n");
if (!gimple)
fprintf (f, "if (TREE_SIDE_EFFECTS (t)) return false;\n");
dt.root->gen_kids (f, gimple);
fprintf (f, "return false;\n"
"}\n");
}
Index: gcc/match.pd
===================================================================
--- gcc/match.pd (revision 223630)
+++ gcc/match.pd (working copy)
@@ -1131,10 +1131,106 @@ along with GCC; see the file COPYING3.
&& (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
|| tree_int_cst_sgn (@4) >= 0)
&& single_use (@5))
(if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
(with { tree ntype = TREE_TYPE (@0); }
(convert (bit_and (op @0 @1) (convert:ntype @4)))))
(with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
(convert (bit_and (op (convert:utype @0) (convert:utype @1))
(convert:utype @4)))))))
+
+(match zerop integer_zerop)
+(match zerop real_zerop)
+
+/* If we have A op 0 ? A : -A, consider applying the following
+ transformations:
+
+ A == 0? A : -A same as -A
+ A != 0? A : -A same as A
+ A >= 0? A : -A same as abs (A)
+ A > 0? A : -A same as abs (A)
+ A <= 0? A : -A same as -abs (A)
+ A < 0? A : -A same as -abs (A)
+
+ None of these transformations work for modes with signed
+ zeros. If A is +/-0, the first two transformations will
+ change the sign of the result (from +0 to -0, or vice
+ versa). The last four will fix the sign of the result,
+ even though the original expressions could be positive or
+ negative, depending on the sign of A.
+
+ Note that all these transformations are correct if A is
+ NaN, since the two alternatives (A and -A) are also NaNs. */
+(if (!HONOR_SIGNED_ZEROS (type))
+ (for cnd (cond vec_cond)
+ (for cmp (tcc_comparison)
+ (simplify
+ (cnd (cmp @0 zerop) (convert?@2 @0) (negate@1 @2))
+ (if (cmp == EQ_EXPR || cmp == UNEQ_EXPR)
+ @1)
+ (if (cmp == NE_EXPR || cmp == LTGT_EXPR)
+ (non_lvalue @2))
+ (if (TYPE_SIGN (TREE_TYPE (@0)) == SIGNED /* implicit */
+ && TYPE_SIGN (type) == SIGNED
+ && element_precision (type) >= element_precision (TREE_TYPE (@0)))
+ (if (cmp == GE_EXPR || cmp == GT_EXPR
+ || (!flag_trapping_math && (cmp == UNGE_EXPR || cmp == UNGT_EXPR)))
+ (abs @2))
+ (if (cmp == LE_EXPR || cmp == LT_EXPR
+ || (!flag_trapping_math && (cmp == UNLE_EXPR || cmp == UNLT_EXPR)))
+ (negate (abs @2)))))
+ /* Now with the branches swapped. */
+ (simplify
+ (cnd (cmp @0 zerop) (negate@1 (convert?@2 @0)) @2)
+ (if (cmp == EQ_EXPR || cmp == UNEQ_EXPR)
+ (non_lvalue @2))
+ (if (cmp == NE_EXPR || cmp == LTGT_EXPR)
+ @1)
+ (if (TYPE_SIGN (TREE_TYPE (@0)) == SIGNED /* implicit */
+ && TYPE_SIGN (type) == SIGNED
+ && element_precision (type) >= element_precision (TREE_TYPE (@0)))
+ (if (cmp == GE_EXPR || cmp == GT_EXPR
+ || (!flag_trapping_math && (cmp == UNGE_EXPR || cmp == UNGT_EXPR)))
+ (negate (abs @2)))
+ (if (cmp == LE_EXPR || cmp == LT_EXPR
+ || (!flag_trapping_math && (cmp == UNLE_EXPR || cmp == UNLT_EXPR)))
+ (abs @2))))
+
+ /* Same as above, but if A is X - Y, -A may be spelled Y - X. */
+ (simplify
+ (cnd (cmp (minus@0 @2 @3) zerop) @0 (minus@1 @3 @2))
+ (if (cmp == EQ_EXPR || cmp == UNEQ_EXPR)
+ @1)
+ (if (cmp == NE_EXPR || cmp == LTGT_EXPR)
+ @0)
+ (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type))
+ (if (cmp == GE_EXPR || cmp == GT_EXPR
+ || (!flag_trapping_math && (cmp == UNGE_EXPR || cmp == UNGT_EXPR)))
+ (abs @0))
+ (if (cmp == LE_EXPR || cmp == LT_EXPR
+ || (!flag_trapping_math && (cmp == UNLE_EXPR || cmp == UNLT_EXPR)))
+ (negate (abs @0)))))
+ (simplify
+ (cnd (cmp (minus@0 @2 @3) zerop) (minus@1 @3 @2) @0)
+ (if (cmp == EQ_EXPR || cmp == UNEQ_EXPR)
+ @0)
+ (if (cmp == NE_EXPR || cmp == LTGT_EXPR)
+ @1)
+ (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type))
+ (if (cmp == GE_EXPR || cmp == GT_EXPR
+ || (!flag_trapping_math && (cmp == UNGE_EXPR || cmp == UNGT_EXPR)))
+ (negate (abs @0)))
+ (if (cmp == LE_EXPR || cmp == LT_EXPR
+ || (!flag_trapping_math && (cmp == UNLE_EXPR || cmp == UNLT_EXPR)))
+ (abs @0)))))
+
+ /* A != 0 ? A : 0 is simply A, unless A is -0. Likewise
+ A == 0 ? A : 0 is always 0 unless A is -0. Note that
+ both transformations are correct when A is NaN: A != 0
+ is then true, and A == 0 is false. */
+ (simplify
+ (cnd (ne @0 zerop) (convert? @0) zerop)
+ (non_lvalue (convert @0)))
+ (simplify
+ (cnd (eq @0 zerop) (convert? @0) zerop@1)
+ (non_lvalue (convert @1)))))
next reply other threads:[~2015-05-24 8:34 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-24 12:50 Marc Glisse [this message]
2015-05-24 15:54 ` Marc Glisse
2015-05-26 9:30 ` Richard Biener
2015-06-28 19:43 ` Marc Glisse
2015-06-29 10:31 ` Richard Biener
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.DEB.2.02.1505231828530.22033@stedding.saclay.inria.fr \
--to=marc.glisse@inria.fr \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).