>Because there are no requirements on UB by definition, there's no guarantee that those calls will do the same thing, even on the same runtime, using the same compiler, with the same flags.
Reread my comment. You are talking about behavior not defined by the C standard which I addressed in that comment. Compilers are deterministic. Reproducible builds are a thing.
Reproducibility is an entirely unrelated issue. The same compiler can produce different assembly for the same code depending on the surrounding context, or any number of other reasons. A reproducible build just means that you'll get the same binary each time you build it. Furthermore, the same generated assembly can produce different results each time it's run, as data races do. In that case, the only "definition" comes down to the essentially unknowable physical state of the system.
Ignore how silly the actual code is and notice that the -O0 assembly checks the pointers before dereferencing them while the -O2 assembly does not. Same compiler, same translation unit, different assembly. Calling each with null pointers will behave differently too. Run this with whatever reproducible toolchain you want. Reproducible builds are not about making undefined behavior deterministic, they're a separate and largely unrelated topic.
In order to make this example you showed me you were successfully able to reason about the output of the compiler despite using UB. You understood how things were defined differently for different optimization levels.
I never said it is defined generally. I said that it eventually gets defined as in it may come down to the source code of a specific version of the compiler that defines the behavior.
Reread my comment. You are talking about behavior not defined by the C standard which I addressed in that comment. Compilers are deterministic. Reproducible builds are a thing.