UB has nothing to do with supporting different hardware behaviour.
I thought some of UB was to deal with different CPU behavior. Some CPUs trap on signed overflow; others wrap. Some can do both, either by setting a flag (VAX) or instruction selection (MIPS). Some CPUs, when executing 1 << 100 do 100 rotates; other mask to the bit width of the type (8086 would do all rotates, 80286 started masking).
the compiler encounters some code, and assumes that UB does not happen
I hate that compilers assume that. I know that programmers don’t intentionally want to invoke UB in C, but there are so damn many footguns in C that I seriously doubt any non-trivial C program is completely UB free. And if a compiler can delete NULL checks in certain circumstance (<cough> <cough> GCC <cough>) that it at least should warn about it deleting a NULL check written by a programmer, but I’ve been told that such checks are beyond the ken of compiler writers for some obscure reason.
I thought some of UB was to deal with different CPU behavior.
That’s what implementation defined behavior means.
Let’s say you’re on a machine where integer overflow is defined as trapping. Because it is UB, the fact that it has defined behavior is irrelevant, their are no constraints on the compiler. For example, say you have code that does this:
int foo(int a, int b) {
return a + b;
}
...
int x = INT_MAX;
int y = cond ? 0 : 1;
foo(x, y);
If cond is true, then a + b is INT_MAX + 1 which is UB, so cond must always be false.
It’s really important to understand that the compiler is not detecting this directly, a lot of optimizations are constraint based, and the result of applying those constraints is that UB paths get dropped.
I hate that compilers assume that. I know that programmers don’t intentionally want to invoke UB in C, but there are so damn many footguns in C that I seriously doubt any non-trivial C program is completely UB free.
Yes, but for the majority of cases where this happens, the problem is not that the compiler is assuming UB operations can’t happen. The problem is that operations with well defined behavior are being labeled as UB. Most of the foot guns around “the compiler removed this code” boil down to “the developer wrote code around well defined behavior on the platform, but the spec says it is undefined”. The moment that implementation defined behavior stops being labeled as UB, many of those foot guns go away.
I thought some of UB was to deal with different CPU behavior. Some CPUs trap on signed overflow; others wrap. Some can do both, either by setting a flag (VAX) or instruction selection (MIPS). Some CPUs, when executing
1 << 100do 100 rotates; other mask to the bit width of the type (8086 would do all rotates, 80286 started masking).I hate that compilers assume that. I know that programmers don’t intentionally want to invoke UB in C, but there are so damn many footguns in C that I seriously doubt any non-trivial C program is completely UB free. And if a compiler can delete NULL checks in certain circumstance (<cough> <cough> GCC <cough>) that it at least should warn about it deleting a NULL check written by a programmer, but I’ve been told that such checks are beyond the ken of compiler writers for some obscure reason.
score 1 · canonical
That’s what implementation defined behavior means.
Let’s say you’re on a machine where integer overflow is defined as trapping. Because it is UB, the fact that it has defined behavior is irrelevant, their are no constraints on the compiler. For example, say you have code that does this:
If
condis true, then a + b isINT_MAX + 1which is UB, socondmust always be false.It’s really important to understand that the compiler is not detecting this directly, a lot of optimizations are constraint based, and the result of applying those constraints is that UB paths get dropped.
Yes, but for the majority of cases where this happens, the problem is not that the compiler is assuming UB operations can’t happen. The problem is that operations with well defined behavior are being labeled as UB. Most of the foot guns around “the compiler removed this code” boil down to “the developer wrote code around well defined behavior on the platform, but the spec says it is undefined”. The moment that implementation defined behavior stops being labeled as UB, many of those foot guns go away.
score 1 · canonical
MIPS overflow checking was intended for Ada; AFAIK no mainstream C or C++ compiler used the instructions.
score 1 · canonical