Site Tools


wiki:gcc-assembly

Table of Contents

GCC Assembly

Reading generated assembly is the ground truth when debugging performance—it shows exactly what the CPU will execute. Use -S to generate assembly, and -fverbose-asm to annotate it with source variable names.

gcc -O3 -march=native -S -fverbose-asm hot_loop.c -o hot_loop.s
cat hot_loop.s

The .s file contains x86-64 assembly (or ARM, depending on your target) with source annotations. Each # line is a comment mapping the following assembly back to source.

Example output (simplified):

# hot_loop.c:5: for (int i = 0; i < n; i++)
	xor	%eax, %eax
.L2:
	cmp	%edx, %eax
	jge	.L4
# hot_loop.c:6: result[i] = a[i] + b[i];
	movl	(%rcx,%rax,4), %r8d
	add	(%r8,%rax,4), %r8d
	movl	%r8d, (%r9,%rax,4)
	inc	%eax
	jmp	.L2
.L4:

xor %eax, %eax clears the loop counter. cmp %edx, %eax; jge .L4 checks if i >= n and jumps to the end. movl, add, movl perform the computation. inc %eax increments the counter. This repeats until the condition exits.

Analyzing for performance:

  1. Count instructions in the hot loop—more instructions = slower per iteration
  2. Look for unexpected memory operations—loads and stores are expensive
  3. Check for branch instructions (jmp, jne)—branches can cause pipeline stalls
  4. Verify vectorization happened—look for vmovdqa, vpadd, etc. (AVX instructions)

No vectorization? If you expected -O3 -march=native to use AVX but see only scalar instructions, something blocked vectorization. Use -fopt-info-vec-missed to find out why.

Compiler explorer: Use godbolt.org to paste C code and see generated assembly interactively. Tweak code, change optimization levels, and see the assembly change in real-time. Great for learning.

Cross-reference with perf: After identifying a hot instruction in assembly, use [[perf]] annotate to see the actual sample counts on that instruction:

perf record -g ./app
perf annotate -s hot_function

This combines profiling data with source/assembly, revealing exactly which instruction is a bottleneck.

Disassembly of compiled binaries:

objdump -d ./app | grep -A 30 hot_function

This disassembles the compiled binary (no source annotations, but shows the actual machine code executed).

Optimization hints: Strange assembly patterns sometimes reveal missed optimizations. Examples: - Multiple branches in a hot loop—use conditional moves (cmov) instead - Redundant memory operations—the compiler didn't eliminate dead stores - Excessive function calls—aggressive inlining would help

wiki/gcc-assembly.md · Last modified: by 127.0.0.1