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

            Bug ID: 78952
           Summary: Combine does not convert 8-bit sign-extract to a
                    zero-extract for QImode operations
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ubizjak at gmail dot com
  Target Milestone: ---

Following testcase:

--cut here--
struct S1
{
  char pad1;
  char val;
  short pad2;
};

struct S1 test_add (struct S1 a, struct S1 b)
{
  a.val += b.val;

  return a;
}
--cut here--

genereates unoptimal code on x86_64, since combine doesn't convert sign-extract
in

Trying 7, 9 -> 10:
Failed to match this instruction:
(set (zero_extract:SI (reg/v:SI 95 [ a ])
        (const_int 8 [0x8])
        (const_int 8 [0x8]))
    (subreg:SI (plus:QI (subreg:QI (sign_extract:SI (reg/v:SI 95 [ a ])
                    (const_int 8 [0x8])
                    (const_int 8 [0x8])) 0)
            (reg:QI 98)) 0))

to a zero-extract, as is the case in a similar testcase:

--cut here--
typedef __SIZE_TYPE__ size_t;

struct S1
{
  char pad1;
  char val;
  short pad2;
};

extern char t[256];

void foo (struct S1 a, size_t i)
{
  t[i] = a.val;
}
--cut here--

where:

(insn 8 4 9 2 (set (reg:SI 91)
        (sign_extract:SI (reg/v:SI 88 [ a ])
            (const_int 8 [0x8])
            (const_int 8 [0x8]))) "pr78904-6.c":18 102 {*extvsi}
     (expr_list:REG_DEAD (reg/v:SI 88 [ a ])
        (nil)))
(insn 9 8 0 2 (set (mem/j:QI (plus:DI (reg/v:DI 89 [ i ])
                (symbol_ref:DI ("t") [flags 0x40]  <var_decl 0x7f9e35cd4e10
t>)) [0 t S1 A8])
        (subreg:QI (reg:SI 91) 0)) "pr78904-6.c":18 84 {*movqi_internal}
     (expr_list:REG_DEAD (reg:SI 91)
        (expr_list:REG_DEAD (reg/v:DI 89 [ i ])
            (nil))))

gets simplified to:

Trying 8 -> 9:
Successfully matched this instruction:
(set (mem/j:QI (plus:DI (reg/v:DI 89 [ i ])
            (symbol_ref:DI ("t") [flags 0x40]  <var_decl 0x7f9e35cd4e10 t>)) [0
t S1 A8])
    (subreg:QI (zero_extract:SI (reg/v:SI 88 [ a ])
            (const_int 8 [0x8])
            (const_int 8 [0x8])) 0))

Please note that in both cases, we have QImode operation with 8-bit (QImode)
extracted value. Sign-extracts to a QImode value are nonsensical in both cases,
but only in the former case are converted to a zero-extract.

Reply via email to