I think you must be mis-remembering the details slightly. The comma operator is a sequence-point, so "tmp" must be assigned the value of "a", and f() and g() must both be called with a value that is the value of "a" converted to the type of "tmp". The two functions can be called in either order though (or in parallel) but there is no issue there.
Of course, the compiler can do anything it likes so long as the program's output is equivalent to what I just described. So, for example, it might not allocate a memory location to "tmp", it could just push the value of "a" onto a register and then call f and g with it. Or if f or g do nothing and have no side-effects, the assembly code might not show calls to f and g. But there is no way you could know these things by running the program, which is the whole point.