Skip to main content
๐Ÿ“œ WAYPOINT LESSON

How Optimizers Exploit UB

โญโญโญ advancedโณ 15 min read๐Ÿ“ Lesson 162 of 225

Dead-store elimination, branch deletion, and folding โ€” watched on real computations.

The guarantee you build on

Observable behavior โ€” reads of volatile objects, writes to files, calls to I/O functions โ€” must be preserved exactly. Everything not observable may be reordered, merged, or deleted provided the observable results are unchanged. UB anywhere removes the 'provided'.

Folding in practice

int folded(void)     { int a = 21; int b = 2; return a * b; }
int unfolded(void)   { volatile int a = 21; volatile int b = 2; return a * b; }

At -O2 the first returns the constant 42 without executing a multiply; the second must load, multiply, and store at runtime. Same observable result โ€” that is the contract working.

Why guards disappear

if (p != NULL && *p > 0) use(*p);

The null check survives because dereferencing NULL is UB only if it happens โ€” here it is guarded. But a write *p = 1 earlier in the function without a check licenses the optimizer to delete a later p != NULL test: a null pointer cannot have been dereferenced, so either p is not null or the program is already meaningless. Learning to see these deletions in disassembly (module 13) is what makes the rule concrete.