Is it an obligation of a good C compiler to honor parenthesis order no matter what optimization level or other circumstance?
You have asked a question that is more complex and ambiguous than you may expect.
Any compiler calling itself a “C compiler” should compile the C language properly. And C has strict rules about both the associativity and precedence of operations in an expression. That includes sub-expressions in parentheses. Any expression, which is not causing UB, must produce exactly the same result on any compiler using types with the same properties. Therefore if you write something, any properly working compiler will give an output that is identical to what you have written. The usual issue is that people don’t really understand what they write. ;)
Now comes the problem of ambiguity in the question. You have asked about an order of operations. That has three meanings. It may mean the abstract order of operations, one defined by operators associativity and precedence. In that case the above answer holds. You skipped the variable types, so the image is incomplete, but in general that expression is always equivalent to the one below. Under the assumptions that there is no UBs, that you have chosen suitable types and that Count is never negative:a = 74636;
a *= Count;
a /= 1024;
a *= Count;
a /= 32768;
a *= Count;
RetVal = a;
The second meaning is the actual, low-level implementation. The exact sequence of machine code instructions. A compiler is allowed to reorder them and shift around code freely, possibly even removing them completely, as long as the result on the virtual machine C implements is the same. In other words: if the abstract behavior, as observed from wthin that piece of code, is the same. For an a variable that is 64-bit and certainly 8-bit unsigned Count, a compiler is allowed to write it as below (assuming I haven’t made some mistake ;)):a = Count;
b = a;
prepare_stack_for_calling_some_function();
a *= a;
a *= b;
call_some_other_function();
b = 18659;
a *= b;
b >>= 23;
a /= b;
cleanup_call_to_other_function();
RetVal = a;
The third meaning is how it is actually executed. I can’t tell about any ARM M0+ processor specifically, but for examle on x86_64 architectures you should expect that the processor may reorder instructions itself if that doesn’t affect the abstract outcome as seen from the perspective of the virtual machine the CPU is implementing. That may affect timings and cache contents.