https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91202
--- Comment #8 from Uroš Bizjak <ubizjak at gmail dot com> --- (In reply to Jakub Jelinek from comment #7) > Perhaps we could define patterns for combine like: > (set (match_operand:SI 0 "register_operand" "=q") > (ashiftrt:SI (zero_extend:SI (match_operand:QI 1 > "register_operand" "q")) > (match_operand:QI 2 "nonmemory_operand" "cI"))) > (clobber (reg:CC 17 flags)) > etc. and split them before reload into an insn that does that with a > subreg:QI followed by zero extension (or sign extension in certain cases) > and then hope before reload the zero extension will be cancelled with the > following subreg use (I guess we can't look at immediate uses during > splitting). The split pass is performed quite late in the game, and the narrowed insn would miss combine pass (c.f. Comment #0 for optimization opportunity). > The disadvantage would be that this would match even if we aren't using a > subreg at the end, so would match even the case of: > unsigned int foo (unsigned char a, unsigned char b) > { > return a >> b; > } > and would change the movzbl %dil, %edi; shrq %cl, %edi into shrq %cl, %dil; > movzbl %dil, %edi. Dunno if that is acceptable. I think that much cleaner solution would be to do the transformation in a kind of "narrowing/widening" pass, as proposed by Richard in Comment #3. There, all type data can be easily determined and operation can be narrowed if the target provides adequate set of instructions.