Almost all compilers will do it for integers, because even if a constant collapse might overflow in a different way, overflow may be ignored by the standard, so they can do what they like.
It often will not work for floating point values if it's adhering to strict floating point math; the order of evaluation with floating point math can affect the outcome, so strict compliance can't reorder floating point math.
5.1.2.3 Program execution
[#1] The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.
[#3] In the abstract machine, all expressions are evaluated as specified by the semantics.
[#13] EXAMPLE 5 Rearrangement for floating-point expressions is often restricted because of limitations in precision as well as range. The implementation cannot generally apply the mathematical associative rules for addition or multiplication, nor the distributive rule, because of roundoff error, even in the absence of overflow and underflow. (Source)
It's not describing the use with constants precisely, but it's clearly noting that seemingly equivalent operations are not actually equivalent in the bizarro world that is floating point arithmetic (e.g. x / 5.0
cannot be translated to x * 0.2
with complete equivalence, x + x * y
cannot be equivalently represented as x * (1.0 + y)
).