https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104645

--- Comment #5 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>:

https://gcc.gnu.org/g:d9c03fc27d8147a9401a29739694b214df48a9a2

commit r12-7952-gd9c03fc27d8147a9401a29739694b214df48a9a2
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Fri Apr 1 11:50:41 2022 +0200

    phiopt: Improve value_replacement [PR104645]

    The following patch fixes the P1 regression by reusing existing
    value_replacement code.  That function already has code to
    handle simple preparation statements (casts, and +,&,|,^ binary
    assignments) before a final binary assignment (which can be
    much wider range of ops).  When we have e.g.
          if (y_3(D) == 0)
            goto <bb 4>;
          else
            goto <bb 3>;
         <bb 3>:
          y_4 = y_3(D) & 31;
          _1 = (int) y_4;
          _6 = x_5(D) r<< _1;
         <bb 4>:
          # _2 = PHI <x_5(D)(2), _6(3)>
    the preparation statements y_4 = y_3(D) & 31; and
    _1 = (int) y_4; are handled by constant evaluation, passing through
    y_3(D) = 0 initially and propagating that through the assignments
    with checking that UB isn't invoked.  But the final
    _6 = x_5(D) r<< _1; assign is handled differently, either through
    neutral_element_p or absorbing_element_p.
    In the first function below we now have:
      <bb 2> [local count: 1073741824]:
      if (i_2(D) != 0)
        goto <bb 3>; [50.00%]
      else
        goto <bb 4>; [50.00%]

      <bb 3> [local count: 536870913]:
      _3 = i_2(D) & 1;
      iftmp.0_4 = (int) _3;

      <bb 4> [local count: 1073741824]:
      # iftmp.0_1 = PHI <iftmp.0_4(3), 0(2)>
    where in GCC 11 we had:
      <bb 2> :
      if (i_3(D) != 0)
        goto <bb 3>; [INV]
      else
        goto <bb 4>; [INV]

      <bb 3> :
      i.1_1 = (int) i_3(D);
      iftmp.0_5 = i.1_1 & 1;

      <bb 4> :
      # iftmp.0_2 = PHI <iftmp.0_5(3), 0(2)>
    Current value_replacement can handle the latter as the last
    stmt of middle_bb is a binary op that in this case satisfies
    absorbing_element_p.
    But the former we can't handle, as the last stmt in middle_bb
    is a cast.

    The patch makes it work in that case by pretending all of middle_bb
    are the preparation statements and there is no binary assign at the
    end, so everything is handled through the constant evaluation.
    We simply set at the start of middle_bb the lhs of comparison
    virtually to the rhs, propagate it through and at the end
    see if virtually the arg0 of the PHI is equal to arg1 of it.

    For GCC 13, I think we just should throw away all the neutral/absorbing
    element stuff and do the constant evaluation of the whole middle_bb
    and handle that way all the ops we currently handle in neutral/absorbing
    element.

    2022-04-01  Jakub Jelinek  <ja...@redhat.com>

            PR tree-optimization/104645
            * tree-ssa-phiopt.cc (value_replacement): If assign has
            CONVERT_EXPR_CODE_P rhs_code, treat it like a preparation
            statement with constant evaluation.

            * gcc.dg/tree-ssa/pr104645.c: New test.

Reply via email to