Better be careful though. Sometimes compiler generated output that looks stupid is correct. And what you think is faster, is not faster or correct. Such as signed division by two by strength reduction to a shift. The results are wrong for negative numbers without a fixup.
Compilers also consider whole possible value range. They do reduce the set of possible values based on earlier code. Like if you've previously multiplied a value by two, the compilers know afterwards "value & (~1)" can be safely removed entirely. But the compiler is forced to drop an optimization if there's even one possible value for which the optimization is not valid. Common values for this to occur are for example 0, INT_MIN, INT_MAX, etc.
Compilers also know a lot of cost. Hypothetically speaking (I haven't actually seen following ever happening!) there can be situations where it's faster to multiply by two than to shift left or add to self. Like because of CPU core execution unit availability that the compiler knows about.