Master the fundamental concepts of intermediate representation through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksLLVM IR is the interchange format behind Clang, Rust, Swift, Julia, and many GPU compilers. It is typed, SSA-based, and infinite-register. Reading .ll output at -O0 vs -O2 is how engineers diagnose missed optimizations and undefined-behavior surprises.
A module contains functions. Each function has basic blocks of instructions. Types are explicit: i32, float, pointers. The phi instruction merges SSA values. alloca, load, and store model stack memory.
llvmLoading…
clang -S -emit-llvm foo.c produces .ll text% prefix; globals use @Production compilers embed this step inside a longer pipeline. GCC flows through cpp, cc1, assembly, and ld; Clang uses the driver, Sema, LLVM IR passes, and a target backend. LLVM bitcode, JVM bytecode, and WASM are other familiar IRs at the same layer. The exercise isolates one pass so you can test it alone before chaining it to the next stage.
You will study LLVM IR by compiling C code with Clang and reading the .ll output. This exercise asks you to trace how C constructs map to LLVM instructions and compare unoptimized vs optimized IR for the same source.
Clang can't run in this sandbox, so this task gives you its output: an LLVM IR function, as clang -S -emit-llvm would print it. Write a small .ll analyser that answers the questions engineers ask when reading IR: how many blocks, where control goes, which φ-nodes merge which values, which instructions are used, and where the loops are.
One function in LLVM IR text form:
llvmLoading…
; on a line is a comment. Blank lines are ignored.define line starts the function (it may carry attributes such as #0 after the parameters); } ends it.NAME: starts a block. If the first instruction appears before any label, that block is named entry.%v = OPCODE ... (defines an SSA value) or OPCODE ... (e.g. store, br, ret, call void ..., unreachable).| Terminator | Successors |
|---|---|
br label %X | X |
br i1 %c, label %T, label %F | T, then F |
ret ... | (return) |
unreachable | (unreachable) |
cLoading…
I counts instructions (not labels or comments); V counts instructions that define a % value.%v = OP ... is OP (so %r = call i32 @f() is call).back edges: none.Input:
cLoading…
Output:
cLoading…
br and phi.Hidden tests use typical -O0 output (alloca/load/store, an unlabelled entry block, attributes), nested loops, a call returning a value, and an unreachable block.