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

            Bug ID: 83855
           Summary: [performance] Improve cse optimization for insn with
                    inout ops
           Product: gcc
           Version: 4.8.4
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: zhongyunde at huawei dot com
  Target Milestone: ---

Created attachment 43132
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=43132&action=edit
patch

Now, as we define match_dup in target insn in *.md, so when the cse only try to
replace the SRC and DEST of memory in function cse_insn , see detail as
following:

/* Canonicalize sources and addresses of destinations.
     We do this in a separate pass to avoid problems when a MATCH_DUP is
     present in the insn pattern.  In that case, we want to ensure that
     we don't break the duplicate nature of the pattern.  So we will replace
     both operands at the same time.  Otherwise, we would fail to find an
     equivalent substitution in the loop calling validate_change below.

     We used to suppress canonicalization of DEST if it appears in SRC,
     but we don't do this any more.  */

  for (i = 0; i < n_sets; i++)
    {
      rtx dest = SET_DEST (sets[i].rtl);
      rtx src = SET_SRC (sets[i].rtl);
      rtx new_rtx = canon_reg (src, insn);

      validate_change (insn, &SET_SRC (sets[i].rtl), new_rtx, 1);

      if (GET_CODE (dest) == ZERO_EXTRACT)
        {
          validate_change (insn, &XEXP (dest, 1),
                           canon_reg (XEXP (dest, 1), insn), 1);
          validate_change (insn, &XEXP (dest, 2),
                           canon_reg (XEXP (dest, 2), insn), 1);
        }

      while (GET_CODE (dest) == SUBREG
             || GET_CODE (dest) == ZERO_EXTRACT
             || GET_CODE (dest) == STRICT_LOW_PART)
        dest = XEXP (dest, 0);

      if (MEM_P (dest))
        canon_reg (dest, insn);
    }

so it will not do optimation for insn with inout ops, as we used to use
match_dup to make the inout ops use same registers. 
But some time, we can see some set ops such as reg_147 in insn_34 will be not
used later, so it can be tried to optimized for both reg_147 in insn_34, but
not only for the SRC of reg_147 in insn_34.
(insn 35 31 34 5 (set (reg:VALIGN 147 [ uu ])
        (reg/v:VALIGN 136 [ uu ])) test.c:53 218 {movvalign_internal}
     (expr_list:REG_DEAD (reg/v:VALIGN 136 [ uu ])
        (nil)))

(insn 34 35 38 5 (parallel [
            (set (reg:VALIGN 147 [ uu ])
                (const_int 0 [0]))
            (set (mem:VALIGN (plus:SI (reg/f:SI 126 [ D.2594 ])
                            (const_int 16 [0x10])) [0 MEM[(void *)D.2594_12 +
16B] S16 A8])
                (unspec:VALIGN [
                        (reg:VALIGN 147 [ uu ])
                        (mem:VALIGN (plus:SI (reg/f:SI 126 [ D.2594 ])
                                    (const_int 16 [0x10])) [0 MEM[(void
*)D.2594_12 + 16B] S16 A8])
                    ] UNSPEC_SVA))
        ]) test.c:53 453 {sva_f}
     (expr_list:REG_DEAD (reg/f:SI 126 [ D.2594 ])
        (expr_list:REG_UNUSED (reg:VALIGN 147 [ uu ])

Reply via email to