What the Compiler Thinks
The same index with the column that makes it honest: the condition under which the compiler does NOT do the thing you expected.
| Code says | Compiler thinks | Stage | …unless |
|---|---|---|---|
1 + 2 | Evaluate during compilation; emit the literal 3. | Optimize | The operation can fault or its result depends on the target — a zero divisor, or floating point where the host and target round differently. Then the instruction survives. |
x + 0 on an integer | Algebraic identity. Use x. | Optimize | The operands are floating point, where adding zero to negative zero changes the value and quiets a signalling NaN, so the identity does not hold. |
let t = a * b; and t is never read | Dead value. Delete the instruction. | Optimize | Computing it is observable or can trap — a call with side effects, a volatile access, or an operation the language says faults. Unused is not the same as unobservable. |
the same expression computed twice on one path | The value already exists. Reuse it. | Optimize | An operand may have been redefined in between — including through a pointer the compiler cannot rule out — or keeping the value live to the reuse would force a spill that costs more than the recomputation. |
a call to a small function in a hot path | Inline it, so the caller’s facts and the callee’s code can be optimized together. | Optimize | The function is recursive without a depth bound, is called through a pointer the compiler cannot resolve, is marked never-inline, or the size budget at this optimization level says no. |
obj.method() on a virtual method | Indirect call through the dispatch table. | Optimize | Class-hierarchy or profile information shows a single target, in which case the call becomes direct — guarded by a type check if the evidence is observational rather than a proof. |
a generic function or type | Emit one specialized body per instantiating type. | Type Impl | The language erases instead, keeping one body with a uniform representation — which is why the same source is fast and large in one language and compact and boxed in another. |
a lambda that reads a surrounding local | The local can outlive its frame. Move it to a heap environment. | Lowering | Escape analysis proves the closure never leaves the frame, in which case the environment stays on the stack and the allocation disappears entirely. |
async function with awaits in it | Rewrite the body as a state machine, one resume point per await. | Lowering | The runtime provides real stackful coroutines, in which case suspension saves an actual stack and no source-level rewrite happens at all. |
match with several arms over an enum | Build a decision tree over the discriminant and check the arms for exhaustiveness. | Lowering | The scrutinee type is open — a class hierarchy that can be extended, or a dynamically typed value — so no closed set of cases exists to check against. |
if (c) x = 1; else x = 2; then use x | Two definitions reach one use. Insert a phi at the merge. | SSA | The IR is not in SSA form, in which case the same question is answered by a reaching-definitions analysis instead — more work per query, no phi nodes. |
a function with many simultaneously live values | More live ranges than registers. Spill the cheapest one to a stack slot. | Registers | The ranges do not actually overlap — many names used one after another need one register — or the value is cheap enough to recompute at each use, which rematerialization does instead of spilling. |
a hot loop with invariant work in the body | Hoist the invariant computation into the preheader. | Loops | The computation can fault, in which case hoisting makes it happen on a loop that may run zero times — or the extended live range causes a spill inside the loop, which costs more than it saved. |
a loop over an array with independent iterations | Vectorize: process several iterations per instruction. | Loops | Aliasing cannot be ruled out, the trip count is unknown and too small to amortize the prologue, or the body contains a call or a side effect that has to happen in order. |
signed integer arithmetic in C or C++ | Overflow is undefined, so assume it does not happen and simplify on that basis. | Legality | The type is unsigned, where wrapping is defined, or the build enables a sanitizer or a wrapping flag that turns the assumption into a checked behavior. |
arr[i] in a memory-safe language | Emit a bounds check. | Loops | Range analysis proves the index is within bounds on every path — common for a loop with a known trip count and a monotone index — in which case the check is removed. |
a call into another translation unit | The body is invisible. Assume it touches memory, spill caller-saved registers, do not inline. | Builds | Link-time optimization defers code generation so the linker can see both bodies, or the function is declared in a way that promises what it does not touch. |
a call site that has seen one receiver type for a long time | Specialize for that type behind a guard, and keep a deoptimization path. | JIT | The site is megamorphic, or the code is compiled ahead of time and cannot observe anything — a static compiler has no evidence to speculate on. |
try / catch around a block | No instructions on the non-throwing path. Emit unwind tables for when a throw happens. | Lowering | The implementation uses setjmp-style handling, which does cost on entry — or the target has no unwinder, in which case exceptions are compiled out or forbidden. |
a variable declared volatile | Every access is observable. No caching, no reordering, no elimination. | Legality | You expected it to provide atomicity or cross-thread ordering. It provides neither; that is what atomics with an explicit memory order are for. |
#include of a header | Paste the file in textually, once per translation unit that names it. | Real World | The language has real modules, where the compiler reads a precompiled interface instead — which is what makes an incremental build proportional to the edit. |
constexpr, or a function evaluated at compile time | Run it now and store the result in the binary. | Real World | The arguments are not compile-time constants, or the body reaches something the compile-time evaluator refuses — allocation, I/O, or a construct outside the evaluable subset. |
x: number in TypeScript | Check it, then erase it. The emitted JavaScript contains nothing about it. | Real World | You expected a run-time check at an API boundary. There is none — external data still needs a schema validated at run time. |
a + b in Python | Compile to a bytecode instruction now; decide what addition means when it executes. | Real World | The implementation specializes the instruction after observing the operand types, which is what a JIT or an adaptive interpreter does — the source is unchanged and the cost is not. |
&mut x in Rust | This is the only live path to that memory. Attach a noalias fact and optimize on it. | Type Impl | The code went through an unsafe block that created a second path, in which case the promise is the programmer’s and breaking it is undefined behavior with no diagnostic. |
the debugger prints <optimized out> | That value has no storage at this instruction. | Debug Info | The build is unoptimized, where every local gets a home stack slot precisely so the debugger can always find it. |
a plan or tool call produced by a model | Untrusted source in an untrusted language. Parse it, type it, validate it, then decide whether to run it. | Agents | Nothing. This is the one row with no exception: text that arrives from a generator is input, and treating it as a validated program because it parsed is the mistake the module exists to prevent. |