https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89954
--- Comment #6 from Hongtao.liu <crazylht at gmail dot com> ---
(In reply to Uroš Bizjak from comment #5)
> (In reply to Hongtao.liu from comment #4)
> > It looks like there's splitter in aarch64 which combines
> > load+xor+zero_extend to zero_extend(mem) + xor, x86 doesn't have. The simple
> > way is to add corresponding define_split for x86.
> >
> > ---------x86 dump-----------
> > Failed to match this instruction:
> > (set (reg:SI 85)
> > (sign_extend:SI (xor:QI (mem/c:QI (symbol_ref:DI ("c") [flags 0x2]
> > <var_decl 0x7f94fd2e8c60 c>) [0 c+0 S1 A8])
> > (const_int 1 [0x1]))))
> > -----------dump end----------
>
> Maybe I'm missing something, but I don't think this transformation is
> correct. Please consider the following analysis with the emphasis on the
> sign bit of the QImode operation:
>
> r = sext:HI (xor:QI (a, b)); b IMM
>
> a 0xxxxxxx
> b 0xxxxxxx
> r 00000000 0xxxxxxx
>
> a 1xxxxxxx
> b 0xxxxxxx
> r 11111111 1xxxxxxx
>
> a 0xxxxxxx
> b 1xxxxxxx
> r 11111111 1xxxxxxx
>
> a 1xxxxxxx
> b 1xxxxxxx
> r 00000000 0xxxxxxx
>
> r = xor:HI ((a, b); a ZEXT, b IMM
movzbl maybe confuse you, there's no ZEXT here, just movqi_internal. also at
the stage of combine it is xorqi_1 not xorsi_1, and b here is const_int 1, the
most significant bit is zero.
here's dump before combine.
(insn 5 2 6 2 (set (reg:QI 87 [ c ])
(mem/c:QI (symbol_ref:DI ("c") [flags 0x2] <var_decl 0x7ff23f550c60
c>) [0 c+0 S1 A8])) "test.c":4:14 79 {*movqi_internal}
(nil))
(insn 6 5 7 2 (parallel [
(set (reg:QI 86)
(xor:QI (reg:QI 87 [ c ])
(const_int 1 [0x1])))
(clobber (reg:CC 17 flags))
]) "test.c":4:14 556 {*xorqi_1}
(expr_list:REG_DEAD (reg:QI 87 [ c ])
(expr_list:REG_UNUSED (reg:CC 17 flags)
(expr_list:REG_EQUAL (xor:QI (mem/c:QI (symbol_ref:DI ("c") [flags
0x2] <var_decl 0x7ff23f550c60 c>) [0 c+0 S1 A8])
(const_int 1 [0x1]))
(nil)))))
(insn 7 6 12 2 (set (reg:SI 85)
(sign_extend:SI (reg:QI 86))) "test.c":4:14 156 {extendqisi2}
(expr_list:REG_DEAD (reg:QI 86)
>
> a 00000000 0xxxxxxx
> b 00000000 0xxxxxxx
> r 00000000 0xxxxxxx
>
> a 00000000 1xxxxxxx
> b 00000000 0xxxxxxx
> r 00000000 1xxxxxxx
>
> a 00000000 0xxxxxxx
> b 11111111 1xxxxxxx
> r 11111111 1xxxxxxx
>
> a 00000000 1xxxxxxx
> b 11111111 1xxxxxxx
> r 11111111 0xxxxxxx
>
> As demonstrated above, results differ when sign bit of the value a is set.
>
> The conversion works when the value a is loaded with a sign-extend operation.
>
> r = xor:HI ((a, b); a SEXT, b IMM
>
> a 00000000 0xxxxxxx
> b 00000000 0xxxxxxx
> r 00000000 0xxxxxxx
>
> a 11111111 1xxxxxxx
> b 00000000 0xxxxxxx
> r 11111111 1xxxxxxx
>
> a 00000000 0xxxxxxx
> b 11111111 1xxxxxxx
> r 11111111 1xxxxxxx
>
> a 11111111 1xxxxxxx
> b 11111111 1xxxxxxx
> r 00000000 0xxxxxxx