In fact GCC will virtually always produce optimal code for multiplication by a constant. Targetting AVR, for example (which doesn't always have hardware multiply), GCC produces more compact code if you use '*' than if you use '<<'. Similarly, any attempt I made to multiply by non-round constants using bitshifting and addition led to less compact code.
The one case so far where I've seen better results using tricks like reciprocal multiplication and shifts was when there was no way for gcc to know it could throw away almost half of the bits due to input range limits. It would be kind of nice to have, say, a 19-bit integer type.