https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119103
--- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> --- (In reply to Richard Biener from comment #10) > (In reply to Jakub Jelinek from comment #9) > > Shouldn't we optimize this in match.pd when global range says it is ok or > > during vrp/evrp using local ranges? I mean turn the int shift into > > {,un}signed {char,short} one depending on the shift amount range and casts > > before/after the shift. > > Sure, but I think this is orthogonal to the addressed issues. I think > there are a lot of targets that cannot do shifts on smaller than word_mode > so the question is whether the demotion would result in extensions that > are hard to eliminate later? There were talks about a promotion pass > on GIMPLE in the past as well. We should have both demotion and promotion passes, demotion allows to avoid computation of things we won't ever need to compute due to later casts, and promotion (before/during vectorization for vectorized loops to make the vectorized loop use fewer vector sizes and before expansion if targets prefer so) might result in better code generation over leaving things up to ree/ext-dse/combine and similar passes. Right now, we do aggressive demotion only during FE folding, e.g. on unsigned char foo (unsigned char a, unsigned char b) { unsigned char c = a + b; unsigned char d = a >> b; unsigned char e = a << b; return a * b * c; } the addition and multiplications are demoted to 8-bit, but this only works inside of single statements; and shifts are never demoted because the shift counts could be in the range [bitsize of narrower type, bitsize of int-1], plus we don't have range info in the FEs. We don't demote e.g. for unsigned char foo (unsigned char a, unsigned char b) { int c = a + b; unsigned char d = c; int e = a * b; unsigned char f = e; int g = f * c; return g; } And promotion is something we do during expansion if targets can't do sub-word or sub-32-bit arithmetics.