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

            Bug ID: 91384
           Summary: Compare with negation is not eliminated
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ubizjak at gmail dot com
  Target Milestone: ---

Following testcase:

--cut here--
void foo (void);
void bar (void);

int
test (int a)
{
  int r;

  if (r = -a)
    foo ();
  else
    bar ();

  return r;
}
--cut here--

results in (-O2):

        movl    %edi, %r12d
        negl    %r12d
        testl   %edi, %edi
        je      .L2

The combine pass can't do anything, since it sees:

(insn 6 3 7 2 (parallel [
            (set (reg/v:SI 82 [ <retval> ])
                (neg:SI (reg/v:SI 83 [ a ])))
            (clobber (reg:CC 17 flags))
        ]) "neg.c":9:9 464 {*negsi2_1}
     (expr_list:REG_UNUSED (reg:CC 17 flags)
        (nil)))
(insn 7 6 8 2 (set (reg:CCZ 17 flags)
        (compare:CCZ (reg/v:SI 83 [ a ])
            (const_int 0 [0]))) "neg.c":9:6 7 {*cmpsi_ccno_1}
     (expr_list:REG_DEAD (reg/v:SI 83 [ a ])
        (nil)))

Please note that the compare is with the original value (reg: 83), not with the
result of the negation (reg: 82). Tree optimizers give us:

  r_3 = -a_2(D);
  if (a_2(D) != 0)
    goto <bb 3>; [50.00%]
  else
    goto <bb 4>; [50.00%]

This is a regression from 4.1.2, where the compiler is able to eliminate the
compare:

        movl    %esi, %ebx
        negl    %ebx
        je      .L2

Reply via email to