Why is there spiillage in this program even after using register allocator?

sum.c:

#include <stdio.h>

int main() {
    int n, i, sum = 0;

    printf("Enter the size of the array: ");
    scanf("%d", &n);

    int array[n];

    printf("Enter %d elements:\n", n);
    for (i = 0; i < n; i++) {
        scanf("%d", &array[i]);
    }

    for (i = 0; i < n; i++) {
        sum += array[i];
    }

    printf("Sum of the array elements: %d\n", sum);

    return 0;
}

So I have the above c program that I convert to llvm ir with the following command: clang -O0 -Xclang -disable-O0-optnone -S -emit-llvm sum.c -o sum.ll

Then after I convert this ir file to an assembly file via: llc-17 -regalloc=greedy -filetype=asm sum.ll -o sum.s, I get the following assembly:

	.text
	.file	"sum.c"
	.globl	main                            # -- Begin function main
	.p2align	4, 0x90
	.type	main,@function
main:                                   # @main
	.cfi_startproc
# %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	pushq	%rbx
	subq	$40, %rsp
	.cfi_offset %rbx, -24
	movl	$0, -24(%rbp)
	movl	$0, -20(%rbp)
	movl	$.L.str, %edi
	xorl	%eax, %eax
	callq	printf@PLT
	leaq	-16(%rbp), %rsi
	movl	$.L.str.1, %edi
	xorl	%eax, %eax
	callq	__isoc99_scanf@PLT
	movl	-16(%rbp), %eax
	movq	%rsp, -32(%rbp)
	movq	%rsp, %rbx
	leaq	15(,%rax,4), %rcx
	andq	$-16, %rcx
	subq	%rcx, %rbx
	movq	%rbx, %rsp
	movq	%rax, -40(%rbp)
	movl	-16(%rbp), %esi
	movl	$.L.str.2, %edi
	xorl	%eax, %eax
	callq	printf@PLT
	movl	$0, -12(%rbp)
	.p2align	4, 0x90
.LBB0_1:                                # =>This Inner Loop Header: Depth=1
	movl	-12(%rbp), %eax
	cmpl	-16(%rbp), %eax
	jge	.LBB0_3
# %bb.2:                                #   in Loop: Header=BB0_1 Depth=1
	movslq	-12(%rbp), %rax
	leaq	(%rbx,%rax,4), %rsi
	movl	$.L.str.1, %edi
	xorl	%eax, %eax
	callq	__isoc99_scanf@PLT
	incl	-12(%rbp)
	jmp	.LBB0_1
.LBB0_3:
	movl	$0, -12(%rbp)
	.p2align	4, 0x90
.LBB0_4:                                # =>This Inner Loop Header: Depth=1
	movl	-12(%rbp), %eax
	cmpl	-16(%rbp), %eax
	jge	.LBB0_6
# %bb.5:                                #   in Loop: Header=BB0_4 Depth=1
	movslq	-12(%rbp), %rax
	movl	(%rbx,%rax,4), %eax
	addl	%eax, -20(%rbp)
	incl	-12(%rbp)
	jmp	.LBB0_4
.LBB0_6:
	movl	-20(%rbp), %esi
	movl	$.L.str.3, %edi
	xorl	%eax, %eax
	callq	printf@PLT
	movl	$0, -24(%rbp)
	movq	-32(%rbp), %rsp
	movl	-24(%rbp), %eax
	leaq	-8(%rbp), %rsp
	popq	%rbx
	popq	%rbp
	.cfi_def_cfa %rsp, 8
	retq
.Lfunc_end0:
	.size	main, .Lfunc_end0-main
	.cfi_endproc
                                        # -- End function
	.type	.L.str,@object                  # @.str
	.section	.rodata.str1.1,"aMS",@progbits,1
.L.str:
	.asciz	"Enter the size of the array: "
	.size	.L.str, 30

	.type	.L.str.1,@object                # @.str.1
.L.str.1:
	.asciz	"%d"
	.size	.L.str.1, 3

	.type	.L.str.2,@object                # @.str.2
.L.str.2:
	.asciz	"Enter %d elements:\n"
	.size	.L.str.2, 20

	.type	.L.str.3,@object                # @.str.3
.L.str.3:
	.asciz	"Sum of the array elements: %d\n"
	.size	.L.str.3, 31

	.ident	"Ubuntu clang version 17.0.6 (++20231209124227+6009708b4367-1~exp1~20231209124336.77)"
	.section	".note.GNU-stack","",@progbits

As you can see there is a lot of memory traffic.Why doesn’t the allocator allocate a register for variables “i” “n” and “sum” for the whole duration of the program?What am I missing here about the register allocator?I checked if the greedy register allocator is ran via -debug-pass=Executions and it indeed runs.

It’s because the register allocator works on SSA values, but since you didn’t run any optimization passes, i, n, and sum are not SSA values, but stored in stack allocations (allocas).

The mem2reg pass promotes stack variables to SSA values. If you run your program through that first, there should be fewer memory accesses:

$ opt -passes=mem2reg sum.ll -S -o sum.opt.ll
$ llc -regalloc=greedy -filetype=asm sum.opt.ll -o sum.s

Hi Hans, totally unrelated but do you know how I can query registers allocated to a machine function post RA, full context : How to query which registers are used by a machine function allocated post RA - Beginners - LLVM Discussion Forums

Thanks!this helped.I observed that the allocator prefered the callee saved register r12-r15 and rbx to store variables.Where can I get more information on such behaviour of the register allocator?And what other sources do you recommend for reading about this?