On Wed, Jul 28, 2021 at 4:39 PM Andrew MacLeod <amacl...@redhat.com> wrote:
>
> So Im seeing what appears to me to be inconsistent behaviour.
>
> in pr96094.c we see:
>
> int
> foo (int x)
> {
>    if (x >= 2U)
>      return 34;
>    return 34 / x;
> }
>
> x has a range of [0,1] and since / 0  in undefined, the expectation is
> that we fold this to "return 34" and vrp1 does this:
>
>   <bb 3> [local count: 767403281]:
>    x_6 = ASSERT_EXPR <x_3(D), (unsigned int) x_3(D) <= 1>;
>    _4 = 34 / x_6;
>
>    <bb 4> [local count: 1073741824]:
>    # _2 = PHI <34(2), _4(3)>
>
> Transformed to
>
>   <bb 3> [local count: 767403281]:
>    _4 = 34;
>
>    <bb 4> [local count: 1073741824]:
>    # _2 = PHI <34(2), _4(3)>
>
>
> but if we go to tree-ssa/pr61839_2.c, we see:
>
>    volatile unsigned b = 1U;
>    int c = 1;
>    c = (a + 972195718) % (b ? 2 : 0);
>    if (c == 1)
>      ;
>    else
>      __builtin_abort ();
>
> /* Dont optimize 972195717 / 0 in function foo.  */
> /* { dg-final { scan-tree-dump-times "972195717 / " 1  "evrp" } } */
>
>
> So why is it OK to optimize out the divide in the first case, but not in
> the second??
>
> Furthermore, If I tweak the second testcase to:
>
>    int a = -1;
>    volatile unsigned b = 1U;
>    int c = 1;
>    c = (a + 972195718) / (b ? 2 : 0);
>    if (c == 486097858)
>      ;
>    else
>      __builtin_abort ();
>
>    int d = 1;
>    d = (a + 972195718) / (b ? 1 : 0);
>    if (d == 972195717)
>      ;
>    else
>      __builtin_abort ();
>    return d;
>
> NOte the only difference is the first case divides by 0 or 2, the second
> case by 0 or 1...
>
> we quite happily produce:
>
>   <bb 2> :
>    b ={v} 1;
>    b.1_2 ={v} b;
>    if (b.1_2 != 0)
>      goto <bb 4>; [INV]
>    else
>      goto <bb 3>; [INV]
>
>    <bb 3> :
>
>    <bb 4> :
>    # iftmp.0_7 = PHI <2(2), 0(3)>
>    c_14 = 972195717 / iftmp.0_7;
>    if (c_14 == 486097858)
>      goto <bb 6>; [INV]
>    else
>      goto <bb 5>; [INV]
>
>    <bb 5> :
>    __builtin_abort ();
>
>    <bb 6> :
>    b.2_4 ={v} b;
>    _5 = b.2_4 != 0;
>    _6 = (int) _5;
>    return 972195717;
>
>
> Which has removed the second call to builtin_abort()    (Even before we
> get to EVRP!)
>
> SO the issue doesn't seem to be removing the divide by 0, it seems to be
> a pattern match for [0,1] that is triggering.
>
> I would argue the test case should not be testing for not removing the
> divide by 0...     Because we can now fold c_14 to be 486097858, and I
> think that is a valid transformation?  (assuming no non-call exceptions
> of course)

I think it's a valid transform, even with -fnon-call-exceptions when
-fdelete-dead-exceptions is enabled (like for Ada and C++).

You'd have to dig into history to tell why we added this testcase in that way.

Richard.

>
> Andrew
>

Reply via email to