Generated Code
MIR:
fn make_array(_1: i32) -> () {
debug fallback => _1; // in scope 0 at src/main.rs:19:15: 19:23
let mut _0: (); // return place in scope 0 at src/main.rs:19:30: 19:30
let _2: [i32; 42]; // in scope 0 at src/main.rs:20:9: 20:12
let mut _3: [i32; 42]; // in scope 0 at src/main.rs:4:13: 4:20
let mut _4: i32; // in scope 0 at src/main.rs:20:29: 20:37
let _5: usize; // in scope 0 at src/main.rs:20:43: 20:45
let _6: usize; // in scope 0 at src/main.rs:20:50: 20:52
let _7: usize; // in scope 0 at src/main.rs:20:57: 20:59
let _8: (); // in scope 0 at src/main.rs:21:5: 21:20
let mut _9: &[i32]; // in scope 0 at src/main.rs:21:15: 21:19
let mut _10: &[i32; 42]; // in scope 0 at src/main.rs:21:15: 21:19
let _11: &[i32; 42]; // in scope 0 at src/main.rs:21:15: 21:19
scope 1 {
debug arr => _2; // in scope 1 at src/main.rs:20:9: 20:12
}
scope 2 {
debug arr => _3; // in scope 2 at src/main.rs:4:13: 4:20
}
bb0: {
StorageLive(_2); // scope 0 at src/main.rs:20:9: 20:12
StorageLive(_3); // scope 0 at src/main.rs:4:13: 4:20
StorageLive(_4); // scope 0 at src/main.rs:20:29: 20:37
_4 = _1; // scope 0 at src/main.rs:20:29: 20:37
_3 = [move _4; LEN]; // scope 0 at src/main.rs:4:23: 4:39
StorageDead(_4); // scope 0 at src/main.rs:4:38: 4:39
StorageLive(_5); // scope 2 at src/main.rs:20:43: 20:45
_5 = const 11usize; // scope 2 at src/main.rs:20:43: 20:45
// ty::Const
// + ty: usize
// + val: Value(Scalar(0x000000000000000b))
// mir::Constant
// + span: src/main.rs:20:43: 20:45
// + literal: Const { ty: usize, val: Value(Scalar(0x000000000000000b)) }
_3[_5] = const 1i32; // scope 2 at src/main.rs:5:11: 5:19
// ty::Const
// + ty: i32
// + val: Value(Scalar(0x00000001))
// mir::Constant
// + span: src/main.rs:20:47: 20:48
// + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
StorageDead(_5); // scope 2 at src/main.rs:5:26: 5:27
StorageLive(_6); // scope 2 at src/main.rs:20:50: 20:52
_6 = const 22usize; // scope 2 at src/main.rs:20:50: 20:52
// ty::Const
// + ty: usize
// + val: Value(Scalar(0x0000000000000016))
// mir::Constant
// + span: src/main.rs:20:50: 20:52
// + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000016)) }
_3[_6] = const 2i32; // scope 2 at src/main.rs:5:11: 5:19
// ty::Const
// + ty: i32
// + val: Value(Scalar(0x00000002))
// mir::Constant
// + span: src/main.rs:20:54: 20:55
// + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) }
StorageDead(_6); // scope 2 at src/main.rs:5:26: 5:27
StorageLive(_7); // scope 2 at src/main.rs:20:57: 20:59
_7 = const 33usize; // scope 2 at src/main.rs:20:57: 20:59
// ty::Const
// + ty: usize
// + val: Value(Scalar(0x0000000000000021))
// mir::Constant
// + span: src/main.rs:20:57: 20:59
// + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000021)) }
_3[_7] = const 3i32; // scope 2 at src/main.rs:5:11: 5:19
// ty::Const
// + ty: i32
// + val: Value(Scalar(0x00000003))
// mir::Constant
// + span: src/main.rs:20:61: 20:62
// + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) }
StorageDead(_7); // scope 2 at src/main.rs:5:26: 5:27
_2 = _3; // scope 2 at src/main.rs:6:9: 6:12
StorageDead(_3); // scope 0 at src/main.rs:7:5: 7:6
StorageLive(_8); // scope 1 at src/main.rs:21:5: 21:20
StorageLive(_9); // scope 1 at src/main.rs:21:15: 21:19
StorageLive(_10); // scope 1 at src/main.rs:21:15: 21:19
StorageLive(_11); // scope 1 at src/main.rs:21:15: 21:19
_11 = &_2; // scope 1 at src/main.rs:21:15: 21:19
_10 = _11; // scope 1 at src/main.rs:21:15: 21:19
_9 = move _10 as &[i32] (Pointer(Unsize)); // scope 1 at src/main.rs:21:15: 21:19
StorageDead(_10); // scope 1 at src/main.rs:21:18: 21:19
_8 = const use_array(move _9) -> bb1; // scope 1 at src/main.rs:21:5: 21:20
// ty::Const
// + ty: for<'r> fn(&'r [i32]) {use_array}
// + val: Value(Scalar(<ZST>))
// mir::Constant
// + span: src/main.rs:21:5: 21:14
// + literal: Const { ty: for<'r> fn(&'r [i32]) {use_array}, val: Value(Scalar(<ZST>)) }
}
bb1: {
StorageDead(_9); // scope 1 at src/main.rs:21:19: 21:20
StorageDead(_11); // scope 1 at src/main.rs:21:20: 21:21
StorageDead(_8); // scope 1 at src/main.rs:21:20: 21:21
_0 = const (); // scope 0 at src/main.rs:19:30: 22:2
// ty::Const
// + ty: ()
// + val: Value(Scalar(<ZST>))
// mir::Constant
// + span: src/main.rs:19:30: 22:2
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
StorageDead(_2); // scope 0 at src/main.rs:22:1: 22:2
return; // scope 0 at src/main.rs:22:2: 22:2
}
}
; Function Attrs: noinline nonlazybind uwtable
define void @make_array(i32 %fallback) unnamed_addr #2 {
start:
%arr1 = alloca [42 x i32], align 16
%arr = alloca [42 x i32], align 4
%0 = bitcast [42 x i32]* %arr to i8*
call void @llvm.lifetime.start.p0i8(i64 168, i8* nonnull %0)
%1 = bitcast [42 x i32]* %arr1 to i8*
call void @llvm.lifetime.start.p0i8(i64 168, i8* nonnull %1)
%2 = insertelement <4 x i32> undef, i32 %fallback, i32 0
%3 = shufflevector <4 x i32> %2, <4 x i32> undef, <4 x i32> zeroinitializer
%4 = bitcast [42 x i32]* %arr1 to <4 x i32>*
store <4 x i32> %3, <4 x i32>* %4, align 16
%5 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 4
%6 = bitcast i32* %5 to <4 x i32>*
store <4 x i32> %3, <4 x i32>* %6, align 16
%7 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 8
store i32 %fallback, i32* %7, align 16
%8 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 9
store i32 %fallback, i32* %8, align 4
%9 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 10
store i32 %fallback, i32* %9, align 8
%10 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 12
%11 = bitcast i32* %10 to <4 x i32>*
store <4 x i32> %3, <4 x i32>* %11, align 16
%12 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 16
store i32 %fallback, i32* %12, align 16
%13 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 17
%14 = bitcast i32* %13 to <4 x i32>*
store <4 x i32> %3, <4 x i32>* %14, align 4
%15 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 21
store i32 %fallback, i32* %15, align 4
%16 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 23
%17 = bitcast i32* %16 to <4 x i32>*
store <4 x i32> %3, <4 x i32>* %17, align 4
%18 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 27
%19 = bitcast i32* %18 to <4 x i32>*
store <4 x i32> %3, <4 x i32>* %19, align 4
%20 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 31
store i32 %fallback, i32* %20, align 4
%21 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 32
store i32 %fallback, i32* %21, align 16
%22 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 34
store i32 %fallback, i32* %22, align 8
%23 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 35
%24 = bitcast i32* %23 to <4 x i32>*
store <4 x i32> %3, <4 x i32>* %24, align 4
%25 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 39
store i32 %fallback, i32* %25, align 4
%26 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 40
store i32 %fallback, i32* %26, align 16
%27 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 41
store i32 %fallback, i32* %27, align 4
%28 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 11
store i32 1, i32* %28, align 4
%29 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 22
store i32 2, i32* %29, align 8
%30 = getelementptr inbounds [42 x i32], [42 x i32]* %arr1, i64 0, i64 33
store i32 3, i32* %30, align 4
call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 4 %0, i8* nonnull align 16 %1, i64 168, i1 false)
call void @llvm.lifetime.end.p0i8(i64 168, i8* nonnull %1)
%_9.0 = bitcast [42 x i32]* %arr to [0 x i32]*
call void @use_array([0 x i32]* noalias nonnull readonly align 4 %_9.0, i64 42)
call void @llvm.lifetime.end.p0i8(i64 168, i8* nonnull %0)
ret void
}
Generated ASM (on the playground)
make_array: # @make_array
# %bb.0:
pushq %rbx
subq $336, %rsp # imm = 0x150
movd %edi, %xmm0
pshufd $0, %xmm0, %xmm0 # xmm0 = xmm0[0,0,0,0]
movdqa %xmm0, (%rsp)
movdqa %xmm0, 16(%rsp)
movl %edi, 32(%rsp)
movl %edi, 36(%rsp)
movl %edi, 40(%rsp)
movdqa %xmm0, 48(%rsp)
movl %edi, 64(%rsp)
movdqu %xmm0, 68(%rsp)
movl %edi, 84(%rsp)
movdqu %xmm0, 92(%rsp)
movdqu %xmm0, 108(%rsp)
movl %edi, 124(%rsp)
movl %edi, 128(%rsp)
movl %edi, 136(%rsp)
movdqu %xmm0, 140(%rsp)
movl %edi, 156(%rsp)
movl %edi, 160(%rsp)
movl %edi, 164(%rsp)
movl $1, 44(%rsp)
movl $2, 88(%rsp)
movl $3, 132(%rsp)
leaq 168(%rsp), %rbx
movq %rsp, %rsi
movl $168, %edx
movq %rbx, %rdi
callq *memcpy@GOTPCREL(%rip)
movl $42, %esi
movq %rbx, %rdi
callq use_array
addq $336, %rsp # imm = 0x150
popq %rbx
retq
# -- End function
That's probably a bit more dumped low level representation than necessary, but the important note is one specific line of asm:
This is proof that the temporary is not getting optimized out with this specific macro and invocation, and that the compiler could do better here. (Either by the language providing a way of writing this inplace, or just by optimizing this better (NRVO for the scope).)