https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78904
Bug ID: 78904 Summary: zero-extracts are not effective Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: ubizjak at gmail dot com Target Milestone: --- Following testcase: --cut here-- struct S1 { char pad1; unsigned char val; short pad2; }; struct S1 test (struct S1 a, struct S1 b) { struct S1 r = a; r.val = a.val + b.val; return r; } --cut here-- should be compiled to something involving: addb %dh, %ah but is compiled to a whole sequence of: movl %edi, %ecx movl %esi, %eax xorl %edx, %edx movzbl %ch, %esi movzbl %ah, %eax movb %dil, %dl addl %esi, %eax xorw %di, %di movb %al, %dh movzwl %dx, %eax orl %edi, %eax The relevant patterns from i386.md are: (define_insn "addqi_ext_1" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q") (const_int 8) (const_int 8)) (plus:SI (zero_extract:SI (match_operand 1 "ext_register_operand" "0,0") (const_int 8) (const_int 8)) (match_operand:QI 2 "general_operand" "Qn,Bn"))) (clobber (reg:CC FLAGS_REG))] and (define_insn "*addqi_ext_2" [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q") (const_int 8) (const_int 8)) (plus:SI (zero_extract:SI (match_operand 1 "ext_register_operand" "%0") (const_int 8) (const_int 8)) (zero_extract:SI (match_operand 2 "ext_register_operand" "Q") (const_int 8) (const_int 8)))) (clobber (reg:CC FLAGS_REG))] Combine pass tries to generate something resembling the above patterns: (set (zero_extract:SI (reg:SI 92 [ D.1804 ]) (const_int 8 [0x8]) (const_int 8 [0x8])) (subreg:SI (plus:QI (subreg:QI (zero_extract:SI (reg/v:SI 95 [ b ]) (const_int 8 [0x8]) (const_int 8 [0x8])) 0) (reg:QI 98 [ a$val ])) 0)) but it looks that the pattern is not fully canonicalized and thus not recognized.