diff mbox

Refine type conversion in result expressions for cond_expr pattern

Message ID CAHFci2_AQDsRFnAJ5qt7EvGTuU643gMXjoyiDtRnig+qcOQ2Xg@mail.gmail.com
State New
Headers show

Commit Message

Bin.Cheng Nov. 23, 2016, 2:57 p.m. UTC
On Wed, Nov 23, 2016 at 2:27 PM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Wed, Nov 23, 2016 at 2:54 PM, Bin Cheng <Bin.Cheng@arm.com> wrote:
>> Hi,
>> This is actually the review suggestion for patch @https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02341.html, but I forgot to incorporate it when committing that patch.  Here comes this one doing that, as well as adding a missing convert keyword.  Toolchain built successfully, is it OK?
>
> As said you _do_ need the outermost (convert ...) on the (max .. and
> (min ... expressions given @1 may not be of type 'type'.
Sorry about the stupid mistake.  How about this one?  The from_type in
the last branch looks like necessary to me.

Thanks,
bin
>
>> Thanks,
>> bin
>>
>> 2016-11-23  Bin Cheng  <bin.cheng@arm.com>
>>
>>         * match.pd: Refine type conversion in result expressions for below
>>         pattern:
>>         (cond (cmp (convert1? x) c1) (convert2? x) c2) -> (minmax (x c)).

Comments

Richard Biener Nov. 24, 2016, 8:57 a.m. UTC | #1
On Wed, Nov 23, 2016 at 3:57 PM, Bin.Cheng <amker.cheng@gmail.com> wrote:
> On Wed, Nov 23, 2016 at 2:27 PM, Richard Biener
> <richard.guenther@gmail.com> wrote:
>> On Wed, Nov 23, 2016 at 2:54 PM, Bin Cheng <Bin.Cheng@arm.com> wrote:
>>> Hi,
>>> This is actually the review suggestion for patch @https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02341.html, but I forgot to incorporate it when committing that patch.  Here comes this one doing that, as well as adding a missing convert keyword.  Toolchain built successfully, is it OK?
>>
>> As said you _do_ need the outermost (convert ...) on the (max .. and
>> (min ... expressions given @1 may not be of type 'type'.
> Sorry about the stupid mistake.  How about this one?  The from_type in
> the last branch looks like necessary to me.

I think

     (if (code == EQ_EXPR)
      (cond (cmp @1 (convert @3)) (convert @3) @2)))))))

is better?  We want the outer expression of type 'type' and @2 is
already 'type',
only @3 may not be.  So the only change would be to dop the unnecessary
:from_type inside the cmp and the bogus :from_type on the true arg of the cond.

Richard.


> Thanks,
> bin
>>
>>> Thanks,
>>> bin
>>>
>>> 2016-11-23  Bin Cheng  <bin.cheng@arm.com>
>>>
>>>         * match.pd: Refine type conversion in result expressions for below
>>>         pattern:
>>>         (cond (cmp (convert1? x) c1) (convert2? x) c2) -> (minmax (x c)).
Bin.Cheng Nov. 24, 2016, 10:11 a.m. UTC | #2
On Thu, Nov 24, 2016 at 8:57 AM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Wed, Nov 23, 2016 at 3:57 PM, Bin.Cheng <amker.cheng@gmail.com> wrote:
>> On Wed, Nov 23, 2016 at 2:27 PM, Richard Biener
>> <richard.guenther@gmail.com> wrote:
>>> On Wed, Nov 23, 2016 at 2:54 PM, Bin Cheng <Bin.Cheng@arm.com> wrote:
>>>> Hi,
>>>> This is actually the review suggestion for patch @https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02341.html, but I forgot to incorporate it when committing that patch.  Here comes this one doing that, as well as adding a missing convert keyword.  Toolchain built successfully, is it OK?
>>>
>>> As said you _do_ need the outermost (convert ...) on the (max .. and
>>> (min ... expressions given @1 may not be of type 'type'.
>> Sorry about the stupid mistake.  How about this one?  The from_type in
>> the last branch looks like necessary to me.
>
> I think
>
>      (if (code == EQ_EXPR)
>       (cond (cmp @1 (convert @3)) (convert @3) @2)))))))
>
> is better?  We want the outer expression of type 'type' and @2 is
> already 'type',
> only @3 may not be.  So the only change would be to dop the unnecessary
> :from_type inside the cmp and the bogus :from_type on the true arg of the cond.
Hi Richard,
The idea of using from_type in EQ_EXPR case is to do cond_expr in
narrow/from type for all its operands, then convert the result back to
default type.
-      (cond (cmp @1 (convert:from_type @3)) (convert:from_type @3) @2)))))))
+      (convert (cond (cmp @1 (convert @3))
+     (convert:from_type @3) (convert:from_type @2)))))))))

Is it better than using different types for operand 0 and 1/2 in cond_expr?
I updated the patch following your suggestion.  Note, in this way
below range check on @2 should be redundant for EQ_EXPR case, but I
didn't change that in this patch.

     if (int_fits_type_p (@2, from_type)
     && (types_match (c1_type, from_type)
         || (TYPE_PRECISION (c1_type) > TYPE_PRECISION (from_type)
         && (TYPE_UNSIGNED (from_type)
             || TYPE_SIGN (c1_type) == TYPE_SIGN (from_type))))

So which one should be preferred?

Thanks,
bin
>
> Richard.
>
>
>> Thanks,
>> bin
>>>
>>>> Thanks,
>>>> bin
>>>>
>>>> 2016-11-23  Bin Cheng  <bin.cheng@arm.com>
>>>>
>>>>         * match.pd: Refine type conversion in result expressions for below
>>>>         pattern:
>>>>         (cond (cmp (convert1? x) c1) (convert2? x) c2) -> (minmax (x c)).
Richard Biener Nov. 24, 2016, 11:17 a.m. UTC | #3
On Thu, Nov 24, 2016 at 11:11 AM, Bin.Cheng <amker.cheng@gmail.com> wrote:
> On Thu, Nov 24, 2016 at 8:57 AM, Richard Biener
> <richard.guenther@gmail.com> wrote:
>> On Wed, Nov 23, 2016 at 3:57 PM, Bin.Cheng <amker.cheng@gmail.com> wrote:
>>> On Wed, Nov 23, 2016 at 2:27 PM, Richard Biener
>>> <richard.guenther@gmail.com> wrote:
>>>> On Wed, Nov 23, 2016 at 2:54 PM, Bin Cheng <Bin.Cheng@arm.com> wrote:
>>>>> Hi,
>>>>> This is actually the review suggestion for patch @https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02341.html, but I forgot to incorporate it when committing that patch.  Here comes this one doing that, as well as adding a missing convert keyword.  Toolchain built successfully, is it OK?
>>>>
>>>> As said you _do_ need the outermost (convert ...) on the (max .. and
>>>> (min ... expressions given @1 may not be of type 'type'.
>>> Sorry about the stupid mistake.  How about this one?  The from_type in
>>> the last branch looks like necessary to me.
>>
>> I think
>>
>>      (if (code == EQ_EXPR)
>>       (cond (cmp @1 (convert @3)) (convert @3) @2)))))))
>>
>> is better?  We want the outer expression of type 'type' and @2 is
>> already 'type',
>> only @3 may not be.  So the only change would be to dop the unnecessary
>> :from_type inside the cmp and the bogus :from_type on the true arg of the cond.
> Hi Richard,
> The idea of using from_type in EQ_EXPR case is to do cond_expr in
> narrow/from type for all its operands, then convert the result back to
> default type.

I see.

> -      (cond (cmp @1 (convert:from_type @3)) (convert:from_type @3) @2)))))))
> +      (convert (cond (cmp @1 (convert @3))
> +     (convert:from_type @3) (convert:from_type @2)))))))))
>
> Is it better than using different types for operand 0 and 1/2 in cond_expr?

Ah, that's a valid point...

> I updated the patch following your suggestion.  Note, in this way
> below range check on @2 should be redundant for EQ_EXPR case, but I
> didn't change that in this patch.
>
>      if (int_fits_type_p (@2, from_type)
>      && (types_match (c1_type, from_type)
>          || (TYPE_PRECISION (c1_type) > TYPE_PRECISION (from_type)
>          && (TYPE_UNSIGNED (from_type)
>              || TYPE_SIGN (c1_type) == TYPE_SIGN (from_type))))
>
> So which one should be preferred?

I suppose it's better to use the same type and thus your version then
(-20161123).
That patch is ok.

Note my worry here is usually that we already have conflicting foldings in this
area (moving conversions in/out), see fold_unary:

          /* If this was a conversion, and all we did was to move into
             inside the COND_EXPR, bring it back out.  But leave it if
             it is a conversion from integer to integer and the
             result precision is no wider than a word since such a
             conversion is cheap and may be optimized away by combine,
             while it couldn't if it were outside the COND_EXPR.  Then return
             so we don't get into an infinite recursion loop taking the
             conversion out and then back in.  */

          if ((CONVERT_EXPR_CODE_P (code)
               || code == NON_LVALUE_EXPR)
              && TREE_CODE (tem) == COND_EXPR
              && TREE_CODE (TREE_OPERAND (tem, 1)) == code
              && TREE_CODE (TREE_OPERAND (tem, 2)) == code
              && ! VOID_TYPE_P (TREE_OPERAND (tem, 1))
              && ! VOID_TYPE_P (TREE_OPERAND (tem, 2))
              && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))
                  == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 2), 0)))
              && (! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
                     && (INTEGRAL_TYPE_P
                         (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
                     && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD)
                  || flag_syntax_only))
            tem = build1_loc (loc, code, type,
                              build3 (COND_EXPR,
                                      TREE_TYPE (TREE_OPERAND
                                                 (TREE_OPERAND (tem, 1), 0)),
                                      TREE_OPERAND (tem, 0),
                                      TREE_OPERAND (TREE_OPERAND (tem, 1), 0),
                                      TREE_OPERAND (TREE_OPERAND (tem, 2),
                                                    0)));

and fold_ternary has quite a bit of COND_EXPR folding as well.

Thanks,
Richard.

>
> Thanks,
> bin
>>
>> Richard.
>>
>>
>>> Thanks,
>>> bin
>>>>
>>>>> Thanks,
>>>>> bin
>>>>>
>>>>> 2016-11-23  Bin Cheng  <bin.cheng@arm.com>
>>>>>
>>>>>         * match.pd: Refine type conversion in result expressions for below
>>>>>         pattern:
>>>>>         (cond (cmp (convert1? x) c1) (convert2? x) c2) -> (minmax (x c)).
Bin.Cheng Nov. 24, 2016, 11:59 a.m. UTC | #4
On Thu, Nov 24, 2016 at 11:17 AM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Thu, Nov 24, 2016 at 11:11 AM, Bin.Cheng <amker.cheng@gmail.com> wrote:
>> On Thu, Nov 24, 2016 at 8:57 AM, Richard Biener
>> <richard.guenther@gmail.com> wrote:
>>> On Wed, Nov 23, 2016 at 3:57 PM, Bin.Cheng <amker.cheng@gmail.com> wrote:
>>>> On Wed, Nov 23, 2016 at 2:27 PM, Richard Biener
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Wed, Nov 23, 2016 at 2:54 PM, Bin Cheng <Bin.Cheng@arm.com> wrote:
>>>>>> Hi,
>>>>>> This is actually the review suggestion for patch @https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02341.html, but I forgot to incorporate it when committing that patch.  Here comes this one doing that, as well as adding a missing convert keyword.  Toolchain built successfully, is it OK?
>>>>>
>>>>> As said you _do_ need the outermost (convert ...) on the (max .. and
>>>>> (min ... expressions given @1 may not be of type 'type'.
>>>> Sorry about the stupid mistake.  How about this one?  The from_type in
>>>> the last branch looks like necessary to me.
>>>
>>> I think
>>>
>>>      (if (code == EQ_EXPR)
>>>       (cond (cmp @1 (convert @3)) (convert @3) @2)))))))
>>>
>>> is better?  We want the outer expression of type 'type' and @2 is
>>> already 'type',
>>> only @3 may not be.  So the only change would be to dop the unnecessary
>>> :from_type inside the cmp and the bogus :from_type on the true arg of the cond.
>> Hi Richard,
>> The idea of using from_type in EQ_EXPR case is to do cond_expr in
>> narrow/from type for all its operands, then convert the result back to
>> default type.
>
> I see.
>
>> -      (cond (cmp @1 (convert:from_type @3)) (convert:from_type @3) @2)))))))
>> +      (convert (cond (cmp @1 (convert @3))
>> +     (convert:from_type @3) (convert:from_type @2)))))))))
>>
>> Is it better than using different types for operand 0 and 1/2 in cond_expr?
>
> Ah, that's a valid point...
>
>> I updated the patch following your suggestion.  Note, in this way
>> below range check on @2 should be redundant for EQ_EXPR case, but I
>> didn't change that in this patch.
>>
>>      if (int_fits_type_p (@2, from_type)
>>      && (types_match (c1_type, from_type)
>>          || (TYPE_PRECISION (c1_type) > TYPE_PRECISION (from_type)
>>          && (TYPE_UNSIGNED (from_type)
>>              || TYPE_SIGN (c1_type) == TYPE_SIGN (from_type))))
>>
>> So which one should be preferred?
>
> I suppose it's better to use the same type and thus your version then
> (-20161123).
> That patch is ok.
>
> Note my worry here is usually that we already have conflicting foldings in this
> area (moving conversions in/out), see fold_unary:
>
>           /* If this was a conversion, and all we did was to move into
>              inside the COND_EXPR, bring it back out.  But leave it if
>              it is a conversion from integer to integer and the
>              result precision is no wider than a word since such a
>              conversion is cheap and may be optimized away by combine,
>              while it couldn't if it were outside the COND_EXPR.  Then return
>              so we don't get into an infinite recursion loop taking the
>              conversion out and then back in.  */
>
>           if ((CONVERT_EXPR_CODE_P (code)
>                || code == NON_LVALUE_EXPR)
>               && TREE_CODE (tem) == COND_EXPR
>               && TREE_CODE (TREE_OPERAND (tem, 1)) == code
>               && TREE_CODE (TREE_OPERAND (tem, 2)) == code
>               && ! VOID_TYPE_P (TREE_OPERAND (tem, 1))
>               && ! VOID_TYPE_P (TREE_OPERAND (tem, 2))
>               && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))
>                   == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 2), 0)))
>               && (! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
>                      && (INTEGRAL_TYPE_P
>                          (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
>                      && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD)
>                   || flag_syntax_only))
>             tem = build1_loc (loc, code, type,
>                               build3 (COND_EXPR,
>                                       TREE_TYPE (TREE_OPERAND
>                                                  (TREE_OPERAND (tem, 1), 0)),
>                                       TREE_OPERAND (tem, 0),
>                                       TREE_OPERAND (TREE_OPERAND (tem, 1), 0),
>                                       TREE_OPERAND (TREE_OPERAND (tem, 2),
>                                                     0)));
Yes, this is a potential issue.  I will apply this version at the
moment, we can always fall
back to the other way if the conflict mentioned below becomes a real
problem, especially
for EQ_EXPR case.
>
> and fold_ternary has quite a bit of COND_EXPR folding as well.
The new pattern is moved from fold_cond_expr_with_comparison which in
turn is called
from fold_ternary.  There isn't much conflict between it and the rest
cases in fold_ternary.
IIUC, they target at different simplifications.
I can add comment about conflict with fold_unary in the pattern, but
would like to do that
after fixing ICEs reported in PR78507 and PR78510.

Thanks,
bin

>
> Thanks,
> Richard.
>
>>
>> Thanks,
>> bin
>>>
>>> Richard.
>>>
>>>
>>>> Thanks,
>>>> bin
>>>>>
>>>>>> Thanks,
>>>>>> bin
>>>>>>
>>>>>> 2016-11-23  Bin Cheng  <bin.cheng@arm.com>
>>>>>>
>>>>>>         * match.pd: Refine type conversion in result expressions for below
>>>>>>         pattern:
>>>>>>         (cond (cmp (convert1? x) c1) (convert2? x) c2) -> (minmax (x c)).
diff mbox

Patch

Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(revision 242751)
+++ gcc/match.pd	(working copy)
@@ -2022,11 +2022,12 @@ 
        }
    }
    (if (code == MAX_EXPR)
-    (convert (max @1 (convert:from_type @2)))
+    (convert (max @1 (convert @2)))
     (if (code == MIN_EXPR)
-     (convert (min @1 (convert:from_type @2)))
+     (convert (min @1 (convert @2)))
      (if (code == EQ_EXPR)
-      (cond (cmp @1 (convert:from_type @3)) (convert:from_type @3) @2)))))))
+      (convert (cond (cmp @1 (convert @3))
+		     (convert:from_type @3) (convert:from_type @2)))))))))
 
 (for cnd (cond vec_cond)
  /* A ? B : (A ? X : C) -> A ? B : C.  */