Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If a program fails only with Clang -O2 or -O3, first assume optimization exposed undefined behavior (UB), not that LLVM is broken. Run AddressSanitizer and UndefinedBehaviorSanitizer, isolate the failing compiler stage, reduce the case, and file an LLVM report only when a small, reproducible failure remains independent of a source defect.

First distinguish the failure you are seeing

Symptom Likely investigation Useful evidence
Clang itself crashes or aborts while compiling Classify the pipeline stage, then reduce the compiler input. Crash diagnostic, replay script, reduced source or IR.
The executable compiles but behaves incorrectly or crashes at runtime Prove or disprove source-level UB before suspecting a miscompilation. Sanitizer report, deterministic test, comparison with a known-good build.

An -O0 versus -O2 difference is a strong reason to inspect object lifetimes, bounds, initialization, signed overflow, alignment, aliasing, data races and invalid control flow. Clang’s manual explains that “the optimizer assumes the code has no undefined behavior,” so code containing UB can behave differently at different optimization levels.

1. Capture an exact, replayable failure

Save the complete failing command before changing flags. Record:

  • Clang version or compiler checkout and the complete source revision.
  • Target triple, host operating system and architecture.
  • Language standard, standard-library and linker versions.
  • Optimization, LTO, PGO, sanitizer and code-generation flags.
  • Relevant environment variables, configuration files and response files.
  • Whether the failure is a compiler crash, a diagnostic, a signal, or a runtime misbehavior.

For a Clang process crash, preserve the preprocessed source and replay script emitted by Clang’s crash diagnostic. Those files remove build-system noise and are normally the most useful starting point for a compiler investigation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Check for undefined behavior before blaming LLVM

Run AddressSanitizer and UBSan

Build the smallest failing path with debug information and both sanitizers:

clang -g -O1 -fsanitize=address,undefined -fno-omit-frame-pointer ...

UBSan can diagnose, among other cases, statically detectable out-of-bounds subscripts, invalid shifts, misaligned or null-pointer dereferences, signed integer overflow and several invalid conversions. To stop at the first finding, add an appropriate -fno-sanitize-recover=... option for the checks you are enabling.

Make sanitizer reports actionable

For symbolized UBSan stacks, retain -g -fno-sanitize-merge -fno-omit-frame-pointer, ensure llvm-symbolizer is on PATH, and run with:

UBSAN_OPTIONS=print_stacktrace=1 ./your-program

Fix each reported source defect and rerun the optimized build. A clean sanitizer run does not prove the program is correct, but an identified lifetime, bounds, arithmetic, alignment or race error takes precedence over an LLVM bug report.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use the sanitizer that matches the remaining suspicion

  • MemorySanitizer: use it when an unexplained uninitialized read remains. It requires compatible whole-program instrumentation; compile with debug information, keep llvm-symbolizer available, and choose an optimization level that produces usable traces.
  • TypeSanitizer: consider it for suspected strict-aliasing or type-punning violations. Its documentation warns that higher optimization levels can optimize away some violations, so test at a level where the diagnostic remains observable.

3. Identify which Clang stage fails

Retry the original compilation with:

-emit-llvm -Xclang -disable-llvm-passes

If the crash still occurs, investigate the Clang front end. If it disappears, the optimizer or code generator is implicated; continue with LLVM IR and pass-level testing.

Test a suspected middle-end failure with opt

First emit bitcode, then run the optimizer separately:

clang -emit-llvm -O1 -Xclang -disable-llvm-passes -c input.c -o foo.bc
opt -O3 foo.bc -disable-output

Use -O1 for the input step rather than -O0. Clang’s -O0 commonly adds optnone, which prevents many optimization passes from running and can hide the failure.

4. Reduce the reproducer

Reduce a compiler crash

Create a test script that returns success only when the failure is present. Keep it deterministic and avoid unnecessary build steps. Then reduce the bitcode:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
llvm-reduce --test=path/to/script foo.bc

A good test script should compile or invoke the failing tool, preserve the same relevant target and flags, and return a nonzero status when the failure disappears. Reduction is more effective when the script can converge toward one failing pass instead of a large, multi-stage build.

Reduce a runtime miscompilation

For an executable that is wrong rather than a compiler process that crashes, use OptBisect to identify the optimization pass that changes behavior. Compare a known-good and known-bad toolchain or target while keeping every other flag fixed. Once a pass boundary is identified, reduce the source or bitcode around that pass and retain a test that demonstrates the divergent result.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

5. Decide whether this is an LLVM bug

File an LLVM issue only after sanitizer runs and reduction leave a reproducible failure that does not depend on an identified source-level defect. Classify it as front end, middle-end optimizer or backend code generator, and state whether it is a compiler crash or an executable miscompilation.

Include all reproduction material

  • The smallest command that still reproduces the failure, copied exactly.
  • Compiler release or checkout, target triple, host details and relevant library/linker versions.
  • Complete diagnostics, crash signal or incorrect-output description.
  • Reduced source and, when relevant, reduced LLVM IR or bitcode.
  • Clang’s generated preprocessed files and replay script for a front-end crash.
  • Sanitizer results, including the fact that relevant checks were clean if no defect was found.
  • OptBisect output or the suspected pass when a miscompilation was narrowed to one.
  • Any difference between toolchains or targets, with all other flags held constant.

LLVM’s bug-reporting guidance emphasizes that a report should contain “All information necessary to reproduce the problem.” A compact, deterministic reproducer is more valuable than a large project archive.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Practical mitigation while investigating

  • Correct the UB when a sanitizer identifies it; optimization-level workarounds are not fixes.
  • If one pass is implicated, use a narrowly scoped temporary pass or optimization workaround only to unblock a build, and document the exact affected toolchain and target.
  • Keep a reduced regression test so upgrades can confirm whether the issue is fixed.
  • When only one toolchain or target fails, preserve that distinction; it is evidence, not proof, of a compiler regression.

The Bottom Line

Optimization does not normally create a crash from valid code. It often exposes assumptions your source already violated. Sanitizer evidence, stage isolation, opt/llvm-reduce reduction and a complete replayable report provide the shortest path to separating a source bug from a genuine LLVM regression.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.