How does auto-vectorization work?

I know that some how, when IREE compiles its generated LLVMIR, it doesn’t contain any vectorization, but the machine code that gets emitted does have vector instructions. How does that work?
I ask because I may need to add that functionality into an older version of LLVM. How difficult might that be?

LLVM has a few vectorization pass, for many years. It improves over time but the fundamentals aren’t new. Here is an overview: Auto-Vectorization in LLVM — LLVM 13 documentation

Does that operate on just C code or also LLVM IR?

This is the LLVM doc: the LLVM optimizer is entirely about LLVM IR.
(You would also find optimization post-LLVM IR in the backend infra)

FYI, the very basic path indeed relied on LLVM’s autovectorization, but the more recent pass pipelines have started to integrate more lowerings through the MLIR vector dialect(s).