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

            Bug ID: 126914
           Summary: [17 regressions] noce_try_shifted_store_flag
                    pessimizes "if (c) x = x OP 2^n" on targets with cheap
                    conditional moves
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: liuhongt at gcc dot gnu.org
  Target Milestone: ---

Since r17-2519-ga33f26607eb4f3 ("Improve select across A/A OP C where C is
2^n",
PR target/125731), if-conversion prefers a store-flag + shift + OP sequence
over
a conditional move for "if (c) x = x OP C" when C is a power of two.  On x86_64
it takes 5 instructions than original 4 since setcc has a false dependence and
needs an extra xorl, also original instructions sequence seems to have less
port pressure.

Testcase (t.c):

  long fun_not1 (int a, long b) { if (!(a & 1)) b ^= 8; return b; }

  $ gcc -O2 -march=x86-64-v3 -S t.c

GCC 15 / GCC 16 (good), 4 insns / 15 bytes:

  fun_not1:
          movq    %rsi, %rax
          xorq    $8, %rax
          andl    $1, %edi
          cmovne  %rsi, %rax
          ret


GCC 17 trunk (bad), 5 insns / 16 bytes:

  fun_not1:
          xorl    %eax, %eax
          andl    $1, %edi
          sete    %al
          salq    $3, %rax
          xorq    %rsi, %rax
          ret


More regressed testcases:

  long xor_not (int a, long b) { if (!(a & 1)) b ^= 8;     return b; } 
regressed
  long ior_not (int a, long b) { if (!(a & 1)) b |= 64;    return b; } 
regressed
  long add_not (int a, long b) { if (!(a & 1)) b += 65536; return b; } 
regressed
  long shl_not (int a, long b) { if (!(a & 1)) b <<= 16;   return b; } 
regressed
  long xor_cmp (int a, long b) { if (a > 100)  b ^= 8;     return b; } 
regressed
  long add_cmp (int a, long b) { if (a > 100)  b += 256;   return b; } 
regressed
  long add_ne  (int a, long b) { if (a != 0)   b += 256;   return b; } 
regressed


It's even clearer for add_ne 3 insns vs 5 insns (-O2 -march=x86-64-v3):

  add_ne   GCC 16:  leaq 256(%rsi), %rax     3 insns, 14 bytes; the lea is off
                    testl %edi, %edi                  the critical path
                    cmove %rsi, %rax

           trunk:   xorl %eax, %eax          5 insns, 15 bytes
                    testl %edi, %edi
                    setne %al
                    salq $8, %rax
                    addq %rsi, %rax

Reply via email to