From: Li Jia He <helijia@linux.ibm.com>
To: Richard Biener <rguenther@suse.de>, Andrew Pinski <pinskia@gmail.com>
Cc: Jeff Law <law@redhat.com>, GCC Patches <gcc-patches@gcc.gnu.org>,
Segher Boessenkool <segher@kernel.crashing.org>,
wschmidt@linux.ibm.com
Subject: Re: [PATCH][middle-end/88784] Middle end is missing some optimizations about unsigned
Date: Tue, 02 Jul 2019 07:41:00 -0000 [thread overview]
Message-ID: <bc69c05f-d966-cab7-b79f-a188523f9258@linux.ibm.com> (raw)
In-Reply-To: <alpine.LSU.2.20.1907010920230.10704@zhemvz.fhfr.qr>
[-- Attachment #1: Type: text/plain, Size: 5271 bytes --]
On 2019/7/1 3:30 PM, Richard Biener wrote:
> On Fri, 28 Jun 2019, Andrew Pinski wrote:
>
>> On Thu, Jun 27, 2019 at 9:55 PM Li Jia He <helijia@linux.ibm.com> wrote:
>>>
>>>
>>>
>>> On 2019/6/27 11:48 PM, Jeff Law wrote:
>>>> On 6/27/19 12:11 AM, Li Jia He wrote:
>>>>> Hi,
>>>>>
>>>>> According to the optimizable case described by Qi Feng on
>>>>> issue 88784, we can combine the cases into the following:
>>>>>
>>>>> 1. x > y && x != XXX_MIN --> x > y
>>>>> 2. x > y && x == XXX_MIN --> false
>>>>> 3. x <= y && x == XXX_MIN --> x == XXX_MIN
>>>>>
>>>>> 4. x < y && x != XXX_MAX --> x < y
>>>>> 5. x < y && x == XXX_MAX --> false
>>>>> 6. x >= y && x == XXX_MAX --> x == XXX_MAX
>>>>>
>>>>> 7. x > y || x != XXX_MIN --> x != XXX_MIN
>>>>> 8. x <= y || x != XXX_MIN --> true
>>>>> 9. x <= y || x == XXX_MIN --> x <= y
>>>>>
>>>>> 10. x < y || x != XXX_MAX --> x != UXXX_MAX
>>>>> 11. x >= y || x != XXX_MAX --> true
>>>>> 12. x >= y || x == XXX_MAX --> x >= y
>>>>>
>>>>> Note: XXX_MIN represents the minimum value of type x.
>>>>> XXX_MAX represents the maximum value of type x.
>>>>>
>>>>> Here we don't need to care about whether the operation is
>>>>> signed or unsigned. For example, in the below equation:
>>>>>
>>>>> 'x > y && x != XXX_MIN --> x > y'
>>>>>
>>>>> If the x type is signed int and XXX_MIN is INT_MIN, we can
>>>>> optimize it to 'x > y'. However, if the type of x is unsigned
>>>>> int and XXX_MIN is 0, we can still optimize it to 'x > y'.
>>>>>
>>>>> The regression testing for the patch was done on GCC mainline on
>>>>>
>>>>> powerpc64le-unknown-linux-gnu (Power 9 LE)
>>>>>
>>>>> with no regressions. Is it OK for trunk ?
>>>>>
>>>>> Thanks,
>>>>> Lijia He
>>>>>
>>>>> gcc/ChangeLog
>>>>>
>>>>> 2019-06-27 Li Jia He <helijia@linux.ibm.com>
>>>>> Qi Feng <ffengqi@linux.ibm.com>
>>>>>
>>>>> PR middle-end/88784
>>>>> * gimple-fold.c (and_comparisons_contain_equal_operands): New function.
>>>>> (and_comparisons_1): Use and_comparisons_contain_equal_operands.
>>>>> (or_comparisons_contain_equal_operands): New function.
>>>>> (or_comparisons_1): Use or_comparisons_contain_equal_operands.
>>>> Would this be better done via match.pd? ISTM this transformation would
>>>> be well suited for that framework.
>>>
>>> Hi, Jeff
>>>
>>> I did this because of the following test case:
>>> `
>>> _Bool comp(unsigned x, unsigned y)
>>> {
>>> return x > y && x != 0;
>>> }
>>> `
>>> The gimple file dumped on the power platform is:
>>> `
>>> comp (unsigned int x, unsigned int y)
>>> {
>>> _Bool D.2837;
>>> int iftmp.0;
>>>
>>> if (x > y) goto <D.2841>; else goto <D.2839>;
>>> <D.2841>:
>>> if (x != 0) goto <D.2842>; else goto <D.2839>;
>>> <D.2842>:
>>> iftmp.0 = 1;
>>> goto <D.2840>;
>>> <D.2839>:
>>> iftmp.0 = 0;
>>> <D.2840>:
>>> D.2837 = (_Bool) iftmp.0;
>>> return D.2837;
>>> }
>>> `
>>> However, the gimple file dumped on x86 is
>>> `
>>> comp (unsigned int x, unsigned int y)
>>> {
>>> _Bool D.2837;
>>>
>>> _1 = x > y;
>>> _2 = x != 0;
>>> _3 = _1 & _2;
>>> _4 = (int) _3;
>>> D.2837 = (_Bool) _4;
>>> return D.2837;
>>> }
>>> `
>>>
>>> The reason for the inconsistency between these two behaviors is param
>>> logical-op-non-short-circuit. If we add the pattern to the match.pd
>>> file, we can only optimize the situation in which the statement is in
>>> the same basic block (logical-op-non-short-circuit=1, x86). But for
>>> a cross-basic block (logical-op-non-short-circuit=0, power), match.pd
>>> can't handle this situation.
>>>
>>> Another reason is that I found out maybe_fold_and_comparisons and
>>> maybe_fold_or_comparisons are not only called by ifcombine pass but
>>> also by reassoc pass. Using this method can basically unify param
>>> logical-op-non-short-circuit=0 or 1.
>>
>>
>> As mentioned before ifcombine pass should be using gimple-match
>> instead of fold_build. Try converting ifcombine over to gimple-match
>> infrastructure and add these to match.pd.
>
> Yes, I mentioned that in the PR. The issue is that at the moment
> to combine x > y with x <= y you'd have to build GENERIC trees
> for both or temporary GIMPLE assign with a SSA def (and then feed
> that into the GENERIC or GIMPLE match.pd path).
Hi,
I did some experimentation using âtemporary GIMPLE with a SSA def (and
then feed that into the GIMPLE match.pd pathâ. Could we consider the
code in the attachment(I did a test and the code took effect)?
Thanks,
Lijia He
>
> maybe_fold_and/or_comparisons handle two exploded binary expressions
> while the current match.pd entries handle at most one exploded one
> (the outermost then, either AND or OR). But it would be definitely
> doable to auto-generate maybe_fold_and/or_comparisons from match.pd
> patterns which is what I'd ultimatively suggest to do (in some more
> generalized form maybe). Either with a separate genmatch invocation
> or as part of the --gimple processing (not sure what is more feasible
> here).
>
> I told Li Jia He that I don't expect him to do this work.
>
> Note I didn't review the actual patch yet.
>
> Thanks,
> Richard.
>
[-- Attachment #2: match.diff --]
[-- Type: text/plain, Size: 5980 bytes --]
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index dfb31a02078..9974b491626 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -5789,6 +5789,12 @@ and_comparisons_1 (enum tree_code code1, tree op1a, tree op1b,
return NULL_TREE;
}
+static tree
+do_valueize (tree t)
+{
+ return t;
+}
+
/* 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
@@ -5800,11 +5806,39 @@ 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);
+ tree t1 = fold_build2 (code1, boolean_type_node, op1a, op1b);
+ tree t2 = fold_build2 (code2, boolean_type_node, op2a, op2b);
+
+ tree new_lhs1 = make_ssa_name (TREE_TYPE (t1));
+ tree new_lhs2 = make_ssa_name (TREE_TYPE (t2));
+
+ gassign *gassign1 = gimple_build_assign (new_lhs1, t1);
+ gassign *gassign2 = gimple_build_assign (new_lhs2, t2);
+
+ tree t = gimple_simplify (TRUTH_AND_EXPR, boolean_type_node,
+ gimple_assign_lhs (gassign1),
+ gimple_assign_lhs (gassign2), NULL, do_valueize);
+
+ if (!t)
+ {
+ t = gimple_simplify (TRUTH_AND_EXPR, boolean_type_node,
+ gimple_assign_lhs (gassign2),
+ gimple_assign_lhs (gassign1), NULL, do_valueize);
+ }
+
if (t)
- return t;
- else
- return and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
+ {
+ gimple *def = SSA_NAME_DEF_STMT (t);
+
+ if (!is_gimple_assign (def)
+ || TREE_CODE_CLASS (gimple_assign_rhs_code (def)) != tcc_comparison)
+ return NULL_TREE;
+
+ return fold_build2 (gimple_assign_rhs_code (def), boolean_type_node,
+ gimple_assign_rhs1 (def), gimple_assign_rhs2 (def));
+ }
+
+ return NULL_TREE;
}
/* Helper function for or_comparisons_1: try to simplify the OR of the
diff --git a/gcc/match.pd b/gcc/match.pd
index f8e35e96d22..21a147d0ff1 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1859,6 +1859,101 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
{ wide_int_to_tree (type, (wi::to_wide (@1)
& (bitpos / BITS_PER_UNIT))); }))))
+/* x > y && x != XXX_MIN --> x > y */
+(for and (truth_and bit_and)
+ (simplify
+ (and:c (gt:c@3 @0 @1) (ne @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && (wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2)))))
+ @3)))
+
+/* x > y && x == XXX_MIN --> false */
+(for and (truth_and bit_and)
+ (simplify
+ (and:c (gt:c @0 @1) (eq @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && (wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2)))))
+ { boolean_false_node; })))
+
+/* x <= y && x == XXX_MIN --> x == XXX_MIN */
+(for and (truth_and bit_and)
+ (simplify
+ (and:c (le:c @0 @1) (eq@3 @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && (wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2)))))
+ @3)))
+
+/* x < y && x != XXX_MAX --> x < y */
+(for and (truth_and bit_and)
+ (simplify
+ (and:c (lt:c@3 @0 @1) (ne @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && (wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2)))))
+ @3)))
+
+/* x < y && x == XXX_MAX --> false */
+(for and (truth_and bit_and)
+ (simplify
+ (and:c (lt:c @0 @1) (eq @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && (wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2)))))
+ { boolean_false_node; })))
+
+/* x >= y && x == XXX_MAX --> x == XXX_MAX */
+(for and (truth_and bit_and)
+ (simplify
+ (and:c (ge:c @0 @1) (eq@3 @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && (wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2)))))
+ @3)))
+
+/* x > y || x != XXX_MIN --> x != XXX_MIN */
+(for or (truth_or bit_ior)
+ (simplify
+ (or:c (gt:c @0 @1) (ne@3 @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2))))
+ @3)))
+
+/* x <= y || x != XXX_MIN --> true */
+(for or (truth_or bit_ior)
+ (simplify
+ (or:c (le:c @0 @1) (ne @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2))))
+ { boolean_true_node; })))
+
+/* x <= y || x == XXX_MIN --> x <= y */
+(for or (truth_or bit_ior)
+ (simplify
+ (or:c (le:c@3 @0 @1) (eq @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && wi::eq_p (wi::to_wide (@2), wi::min_value (TREE_TYPE (@2))))
+ @3)))
+
+/* x < y || x != XXX_MAX --> x != XXX_MAX */
+(for or (truth_or bit_ior)
+ (simplify
+ (or:c (lt:c @0 @1) (ne@3 @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2))))
+ @3)))
+
+/* x >= y || x != XXX_MAX --> true */
+(for or (truth_or bit_ior)
+ (simplify
+ (or:c (ge:c @0 @1) (ne @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2))))
+ { boolean_true_node; })))
+
+/* x >= y || x == XXX_MAX --> x >= y */
+(for or (truth_or bit_ior)
+ (simplify
+ (or:c (ge:c@3 @0 @1) (eq @0 INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1))
+ && wi::eq_p (wi::to_wide (@2), wi::max_value (TREE_TYPE (@2))))
+ @3)))
/* We can't reassociate at all for saturating types. */
(if (!TYPE_SATURATING (type))
next prev parent reply other threads:[~2019-07-02 7:41 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-27 6:12 Li Jia He
2019-06-27 15:48 ` Jeff Law
2019-06-28 4:55 ` Li Jia He
2019-06-28 17:02 ` Andrew Pinski
2019-07-01 7:31 ` Richard Biener
2019-07-02 7:41 ` Li Jia He [this message]
2019-07-02 8:09 ` Richard Biener
2019-07-02 8:51 ` Richard Biener
2019-07-16 6:54 ` Li Jia He
2019-08-30 11:16 ` Martin Liška
2019-09-05 13:01 ` Richard Biener
2019-09-05 18:47 ` Martin Liška
2019-09-06 8:01 ` Richard Biener
2019-09-06 8:04 ` Martin Liška
2019-09-06 10:13 ` [PATCH 1/2] Auto-generate maybe_fold_and/or_comparisons from match.pd Martin Liška
2019-09-09 12:23 ` Martin Liška
2019-09-09 13:10 ` Richard Biener
2019-09-09 13:40 ` Martin Liška
2019-09-09 13:42 ` Richard Biener
2019-09-09 13:45 ` Martin Liška
2019-09-09 13:55 ` Richard Biener
2019-09-10 7:40 ` Martin Liška
[not found] ` <ba4ec7b3-0d0d-ca7b-b2d9-2f34478a23f4@linux.ibm.com>
2019-09-11 8:51 ` Martin Liška
2019-09-11 11:16 ` Martin Liška
2019-09-11 12:23 ` Richard Biener
2019-09-11 13:55 ` Martin Liška
2019-09-09 13:10 ` Marc Glisse
2019-09-09 13:30 ` Martin Liška
2019-09-09 13:39 ` Richard Biener
2019-09-09 12:24 ` [PATCH 4/5] Rewrite first part of or_comparisons_1 into match.pd Martin Liška
2019-09-11 11:19 ` Martin Liška
2019-09-11 13:57 ` Martin Liška
2019-09-16 9:05 ` Richard Biener
2019-09-09 12:24 ` [PATCH 3/5] Rewrite part of and_comparisons_1 " Martin Liška
2019-09-09 13:41 ` Martin Liška
2019-09-10 7:41 ` Martin Liška
2019-09-10 11:19 ` Marc Glisse
2019-09-11 8:27 ` Martin Liška
2019-09-11 11:18 ` Martin Liška
2019-09-11 12:44 ` Richard Biener
2019-09-11 13:19 ` Martin Liška
2019-09-11 13:57 ` Martin Liška
2019-09-16 9:04 ` Richard Biener
2019-09-16 13:47 ` Martin Liška
2019-09-10 8:52 ` Bernhard Reutner-Fischer
2019-09-11 8:11 ` Martin Liška
2019-09-09 12:25 ` [PATCH 5/5] Rewrite second part of or_comparisons_1 " Martin Liška
2019-09-11 11:19 ` Martin Liška
2019-09-11 13:57 ` Martin Liška
2019-09-16 9:07 ` Richard Biener
2019-09-16 14:23 ` Martin Liška
2019-09-05 13:17 ` [PATCH][middle-end/88784] Middle end is missing some optimizations about unsigned Richard Biener
2019-09-05 18:47 ` Martin Liška
2019-09-06 10:14 ` [PATCH 2/2] Fix PR88784, middle " Martin Liška
2019-09-11 13:08 ` Richard Biener
2019-09-11 13:56 ` Martin Liška
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=bc69c05f-d966-cab7-b79f-a188523f9258@linux.ibm.com \
--to=helijia@linux.ibm.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=law@redhat.com \
--cc=pinskia@gmail.com \
--cc=rguenther@suse.de \
--cc=segher@kernel.crashing.org \
--cc=wschmidt@linux.ibm.com \
/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).