On Tue, Sep 3, 2019 at 12:34 PM Ilya Leoshkevich <i...@linux.ibm.com> wrote:
>
> > Am 03.09.2019 um 12:07 schrieb Richard Biener <richard.guent...@gmail.com>:
> >
> > On Mon, Sep 2, 2019 at 6:28 PM Ilya Leoshkevich <i...@linux.ibm.com> wrote:
> >>
> >>> Am 02.09.2019 um 12:37 schrieb Richard Biener 
> >>> <richard.guent...@gmail.com>:
> >>>
> >>> On Fri, Aug 30, 2019 at 5:25 PM Ilya Leoshkevich <i...@linux.ibm.com> 
> >>> wrote:
> >>>>
> >>>>> Am 30.08.2019 um 16:40 schrieb Ilya Leoshkevich <i...@linux.ibm.com>:
> >>>>>
> >>>>>> Am 30.08.2019 um 09:12 schrieb Richard Biener 
> >>>>>> <richard.guent...@gmail.com>:
> >>>>>>
> >>>>>> On Thu, Aug 29, 2019 at 5:39 PM Ilya Leoshkevich <i...@linux.ibm.com> 
> >>>>>> wrote:
> >>>>>>>
> >>>>>>>> Am 22.08.2019 um 15:45 schrieb Ilya Leoshkevich <i...@linux.ibm.com>:
> >>>>>>>>
> >>>>>>>> Bootstrap and regtest running on x86_64-redhat-linux and
> >>>>>>>> s390x-redhat-linux.
> >>>>>>>>
> >>>>>>>> This patch series adds signaling FP comparison support (both scalar 
> >>>>>>>> and
> >>>>>>>> vector) to s390 backend.
> >>>>>>>
> >>>>>>> I'm running into a problem on ppc64 with this patch, and it would be
> >>>>>>> great if someone could help me figure out the best way to resolve it.
> >>>>>>>
> >>>>>>> vector36.C test is failing because gimplifier produces the following
> >>>>>>>
> >>>>>>> _5 = _4 > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 };
> >>>>>>> _6 = VEC_COND_EXPR <_5, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>;
> >>>>>>>
> >>>>>>> from
> >>>>>>>
> >>>>>>> VEC_COND_EXPR < (*b > { 2.0e+0, 2.0e+0, 2.0e+0, 2.0e+0 }) ,
> >>>>>>>               { -1, -1, -1, -1 } ,
> >>>>>>>               { 0, 0, 0, 0 } >
> >>>>>>>
> >>>>>>> Since the comparison tree code is now hidden behind a temporary, my 
> >>>>>>> code
> >>>>>>> does not have anything to pass to the backend.  The reason for 
> >>>>>>> creating
> >>>>>>> a temporary is that the comparison can trap, and so the following 
> >>>>>>> check
> >>>>>>> in gimplify_expr fails:
> >>>>>>>
> >>>>>>> if (gimple_seq_empty_p (internal_post) && (*gimple_test_f) (*expr_p))
> >>>>>>> goto out;
> >>>>>>>
> >>>>>>> gimple_test_f is is_gimple_condexpr, and it eventually calls
> >>>>>>> operation_could_trap_p (GT).
> >>>>>>>
> >>>>>>> My current solution is to simply state that backend does not support
> >>>>>>> SSA_NAME in vector comparisons, however, I don't like it, since it may
> >>>>>>> cause performance regressions due to having to fall back to scalar
> >>>>>>> comparisons.
> >>>>>>>
> >>>>>>> I was thinking about two other possible solutions:
> >>>>>>>
> >>>>>>> 1. Change the gimplifier to allow trapping vector comparisons.  That's
> >>>>>>> a bit complicated, because tree_could_throw_p checks not only for
> >>>>>>> floating point traps, but also e.g. for array index out of bounds
> >>>>>>> traps.  So I would have to create a tree_could_throw_p version which
> >>>>>>> disregards specific kinds of traps.
> >>>>>>>
> >>>>>>> 2. Change expand_vector_condition to follow SSA_NAME_DEF_STMT and use
> >>>>>>> its tree_code instead of SSA_NAME.  The potential problem I see with
> >>>>>>> this is that there appears to be no guarantee that _5 will be inlined
> >>>>>>> into _6 at a later point.  So if we say that we don't need to fall
> >>>>>>> back to scalar comparisons based on availability of vector >
> >>>>>>> instruction and inlining does not happen, then what's actually will
> >>>>>>> be required is vector selection (vsel on S/390), which might not be
> >>>>>>> available in general case.
> >>>>>>>
> >>>>>>> What would be a better way to proceed here?
> >>>>>>
> >>>>>> On GIMPLE there isn't a good reason to split out trapping comparisons
> >>>>>> from [VEC_]COND_EXPR - the gimplifier does this for GIMPLE_CONDs
> >>>>>> where it is important because we'd have no way to represent EH info
> >>>>>> when not done.  It might be a bit awkward to preserve EH across RTL
> >>>>>> expansion though in case the [VEC_]COND_EXPR are not expanded
> >>>>>> as a single pattern, but I'm not sure.
> >>>>>
> >>>>> Ok, so I'm testing the following now - for the problematic test that
> >>>>> helped:
> >>>>>
> >>>>> diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
> >>>>> index b0c9f9b671a..940aa394769 100644
> >>>>> --- a/gcc/gimple-expr.c
> >>>>> +++ b/gcc/gimple-expr.c
> >>>>> @@ -602,17 +602,33 @@ is_gimple_lvalue (tree t)
> >>>>>       || TREE_CODE (t) == BIT_FIELD_REF);
> >>>>> }
> >>>>>
> >>>>> -/*  Return true if T is a GIMPLE condition.  */
> >>>>> +/* Helper for is_gimple_condexpr and 
> >>>>> is_possibly_trapping_gimple_condexpr.  */
> >>>>>
> >>>>> -bool
> >>>>> -is_gimple_condexpr (tree t)
> >>>>> +static bool
> >>>>> +is_gimple_condexpr_1 (tree t, bool allow_traps)
> >>>>> {
> >>>>> return (is_gimple_val (t) || (COMPARISON_CLASS_P (t)
> >>>>> -                             && !tree_could_throw_p (t)
> >>>>> +                             && (allow_traps || !tree_could_throw_p 
> >>>>> (t))
> >>>>>                             && is_gimple_val (TREE_OPERAND (t, 0))
> >>>>>                             && is_gimple_val (TREE_OPERAND (t, 1))));
> >>>>> }
> >>>>>
> >>>>> +/*  Return true if T is a GIMPLE condition.  */
> >>>>> +
> >>>>> +bool
> >>>>> +is_gimple_condexpr (tree t)
> >>>>> +{
> >>>>> +  return is_gimple_condexpr_1 (t, false);
> >>>>> +}
> >>>>> +
> >>>>> +/* Like is_gimple_condexpr, but allow the T to trap.  */
> >>>>> +
> >>>>> +bool
> >>>>> +is_possibly_trapping_gimple_condexpr (tree t)
> >>>>> +{
> >>>>> +  return is_gimple_condexpr_1 (t, true);
> >>>>> +}
> >>>>> +
> >>>>> /* Return true if T is a gimple address.  */
> >>>>>
> >>>>> bool
> >>>>> diff --git a/gcc/gimple-expr.h b/gcc/gimple-expr.h
> >>>>> index 1ad1432bd17..20546ca5b99 100644
> >>>>> --- a/gcc/gimple-expr.h
> >>>>> +++ b/gcc/gimple-expr.h
> >>>>> @@ -41,6 +41,7 @@ extern void gimple_cond_get_ops_from_tree (tree, enum 
> >>>>> tree_code *, tree *,
> >>>>>                                        tree *);
> >>>>> extern bool is_gimple_lvalue (tree);
> >>>>> extern bool is_gimple_condexpr (tree);
> >>>>> +extern bool is_possibly_trapping_gimple_condexpr (tree);
> >>>>> extern bool is_gimple_address (const_tree);
> >>>>> extern bool is_gimple_invariant_address (const_tree);
> >>>>> extern bool is_gimple_ip_invariant_address (const_tree);
> >>>>> diff --git a/gcc/gimplify.c b/gcc/gimplify.c
> >>>>> index daa0b71c191..4e6256390c0 100644
> >>>>> --- a/gcc/gimplify.c
> >>>>> +++ b/gcc/gimplify.c
> >>>>> @@ -12973,6 +12973,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, 
> >>>>> gimple_seq *post_p,
> >>>>> else if (gimple_test_f == is_gimple_val
> >>>>>          || gimple_test_f == is_gimple_call_addr
> >>>>>          || gimple_test_f == is_gimple_condexpr
> >>>>> +        || gimple_test_f == is_possibly_trapping_gimple_condexpr
> >>>>>          || gimple_test_f == is_gimple_mem_rhs
> >>>>>          || gimple_test_f == is_gimple_mem_rhs_or_call
> >>>>>          || gimple_test_f == is_gimple_reg_rhs
> >>>>> @@ -13814,7 +13815,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, 
> >>>>> gimple_seq *post_p,
> >>>>>         enum gimplify_status r0, r1, r2;
> >>>>>
> >>>>>         r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
> >>>>> -                             post_p, is_gimple_condexpr, fb_rvalue);
> >>>>> +                             post_p, 
> >>>>> is_possibly_trapping_gimple_condexpr, fb_rvalue);
> >>>>>         r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
> >>>>>                             post_p, is_gimple_val, fb_rvalue);
> >>>>>         r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
> >>>>> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> >>>>> index b75fdb2e63f..175b858f56b 100644
> >>>>> --- a/gcc/tree-cfg.c
> >>>>> +++ b/gcc/tree-cfg.c
> >>>>> @@ -4121,8 +4121,11 @@ verify_gimple_assign_ternary (gassign *stmt)
> >>>>>     return true;
> >>>>>   }
> >>>>>
> >>>>> -  if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR)
> >>>>> -       ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1))
> >>>>> +  if ((rhs_code == VEC_COND_EXPR
> >>>>> +       ? !is_possibly_trapping_gimple_condexpr (rhs1)
> >>>>> +       : (rhs_code == COND_EXPR
> >>>>> +       ? !is_gimple_condexpr (rhs1)
> >>>>> +       : !is_gimple_val (rhs1)))
> >>>>>     || !is_gimple_val (rhs2)
> >>>>>     || !is_gimple_val (rhs3))
> >>>>>   {
> >>>>>
> >>>>>>
> >>>>>> To go this route you'd have to split the is_gimple_condexpr check
> >>>>>> I guess and eventually users turning [VEC_]COND_EXPR into conditional
> >>>>>> code (do we have any?) have to be extra careful then.
> >>>>>>
> >>>>>
> >>>>> We have expand_vector_condition, which turns VEC_COND_EXPR into
> >>>>> COND_EXPR - but this should be harmless, right?  I could not find
> >>>>> anything else.
> >>>>
> >>>> Ugh, I've realized I need to check not only VEC_COND_EXPR, but also
> >>>> COND_EXPR usages.  There is, of course, a great deal more code, so I'm
> >>>> not sure whether I looked exhaustively through it, but there are at
> >>>> least store_expr and do_jump which do exactly this during expansion.
> >>>> Should we worry about EH edges at this point?
> >>>
> >>> Well, the EH edge needs to persist (and be rooted off the comparison,
> >>> not the selection).
> >>
> >> Ok, I'm trying to create some samples that may reveal problems with EH
> >> edges in these two cases.  So far with these experiments I only managed
> >> to find and unrelated S/390 bug :-)
> >> https://gcc.gnu.org/ml/gcc-patches/2019-09/msg00065.html
> >>
> >>> That said, I'd simply stop using is_gimple_condexpr for GIMPLE_CONDs
> >>> (it allows is_gimple_val which isn't proper form for GIMPLE_COND).  Of 
> >>> course
> >>> there's code using it for GIMPLE_CONDs which would need to be adjusted.
> >>
> >> I'm sorry, I don't quite get this - what would that buy us?  and what
> >> would you use instead?  Right now we fix up non-conforming values
> >> accepted by is_gimple_val using gimple_cond_get_ops_from_tree - is
> >> there a problem with this approach?
> >>
> >> What I have in mind right now is to:
> >> - allow trapping conditions for COND_EXPR and VEC_COND_EXPR;
> >> - report them as trapping in operation_could_trap_p and
> >>  tree_could_trap_p iff their condition is trapping;
> >> - find and adjust all places where this messes up EH edges.
> >>
> >> GIMPLE_COND logic appears to be already covered precisely because it
> >> uses is_gimple_condexpr.
> >>
> >> Am I missing something?
> >
> > Not really - all I'm saying is that currently we use is_gimple_condexpr
> > to check whether a GENERIC tree is suitable for [VEC_]COND_EXPR
> > during for example forward propagation.
> >
> > And GIMPLE_COND already uses its own logic (as you say) but
> > still passes use is_gimple_condexpr for it.
> >
> > So my proposal would be to change is_gimple_condexpr to
> > allow trapping [VEC_]COND_EXPR and stop using is_gimple_condexpr
> > checks on conditions to be used for GIMPLE_CONDs (and substitute
> > another predicate there).  For this to work and catch wrong-doings
> > we should amend gimple_cond_get_ops_from_tree to assert
> > that the extracted condition cannot trap.
>
> Ah, I think now I understand.  While I wanted to keep is_gimple_condexpr
> as is and introduce is_possibly_trapping_gimple_condexpr, you're saying
> we rather need to change is_gimple_condexpr and introduce, say,
> is_non_trapping_gimple_condexpr.
>
> This makes sense, thanks for the explanation!

I'd say is_gimple_cond_expr - bah! stupid clashing names ;)
OK, so is_gimple_cond_condexpr vs. is_gimple_condexpr_cond?
Hmm, no.

I don't like to explicitely spell "non_trapping" here but instead
find names that tell one is for GIMPLE_COND while the
other is for GIMPLE_ASSIGN with a [VEC_]COND_EXPR operation.

Ah, maybe is_gimple_cond_condition () vs. is_gimple_assign_condition ()?
Or is_gimple_condexpr_for_cond and is_gimple_condexpr_for_assign?

Richard.

Reply via email to