We can pass arguments and results in registers without adding a custom calling convention to LLVM. In fact, rustc already generates reasonable results if you request the C calling convention:
pub struct X(*const i32, *const i32);
pub extern "C" fn f(x: X) -> X { x }
Generates:
movq %rdi, %rax
movq %rsi, %rdx
retq
Of course, it’s kind of pathetic that Rust’s default calling convention is worse than the C calling convention… but that can be fixed without a custom LLVM calling convention.