void scatter_double(double *restrict out, const unsigned out_stride,
                    const double *restrict in, const unsigned in_stride,
                    const unsigned int *restrict map) {
  unsigned int i, j;
  while ((i = *map++) != -(unsigned int)1) {
    double t = in[i * in_stride];
    j = *map++;
    do
      out[j * out_stride] = t;
    while ((j = *map++) != -(unsigned int)1);
  }
}


x86 assembly (clang, -O0):
<scatter_double>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
mov    %r8,-0x28(%rbp)
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x4,%rcx
mov    %rcx,-0x28(%rbp)
mov    (%rax),%eax
mov    %eax,-0x2c(%rbp)
cmp    $0xffffffff,%eax
je     1197 <scatter_double+0x97>
mov    -0x18(%rbp),%rax
mov    -0x2c(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
mov    %ecx,%ecx
movsd  (%rax,%rcx,8),%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x4,%rcx
mov    %rcx,-0x28(%rbp)
mov    (%rax),%eax
mov    %eax,-0x30(%rbp)
movsd  -0x38(%rbp),%xmm0
mov    -0x8(%rbp),%rax
mov    -0x30(%rbp),%ecx
imul   -0xc(%rbp),%ecx
mov    %ecx,%ecx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x4,%rcx
mov    %rcx,-0x28(%rbp)
mov    (%rax),%eax
mov    %eax,-0x30(%rbp)
cmp    $0xffffffff,%eax
jne    115e <scatter_double+0x5e>
jmp    1116 <scatter_double+0x16>
pop    %rbp
ret

x86 assembly (clang, -O2):
<scatter_double>:
mov    (%r8),%eax
cmp    $0xffffffff,%eax
je     1136 <scatter_double+0x36>
imul   %ecx,%eax
movsd  (%rdx,%rax,8),%xmm0
mov    0x4(%r8),%eax
add    $0x8,%r8
nopl   0x0(%rax,%rax,1)
imul   %esi,%eax
movsd  %xmm0,(%rdi,%rax,8)
mov    (%r8),%eax
add    $0x4,%r8
cmp    $0xffffffff,%eax
jne    1120 <scatter_double+0x20>
jmp    1100 <scatter_double>
ret

LLVM IR (-O0):
define void @scatter_double(double* noalias %0, i32 %1, double* noalias %2, i32 %3, i32* noalias %4) {
%6 = alloca double*
%7 = alloca i32
%8 = alloca double*
%9 = alloca i32
%10 = alloca i32*
%11 = alloca i32
%12 = alloca i32
%13 = alloca double
store double* %0, double** %6
store i32 %1, i32* %7
store double* %2, double** %8
store i32 %3, i32* %9
store i32* %4, i32** %10
br label %14
14: ; preds = %43, %5
%15 = load i32*, i32** %10
%16 = getelementptr inbounds i32, i32* %15, i32 1
store i32* %16, i32** %10
%17 = load i32, i32* %15
store i32 %17, i32* %11
%18 = icmp ne i32 %17, -1
br i1 %18, label %19, label %44
19: ; preds = %14
%20 = load double*, double** %8
%21 = load i32, i32* %11
%22 = load i32, i32* %9
%23 = mul i32 %21, %22
%24 = zext i32 %23 to i64
%25 = getelementptr inbounds double, double* %20, i64 %24
%26 = load double, double* %25
store double %26, double* %13
%27 = load i32*, i32** %10
%28 = getelementptr inbounds i32, i32* %27, i32 1
store i32* %28, i32** %10
%29 = load i32, i32* %27
store i32 %29, i32* %12
br label %30
30: ; preds = %38, %19
%31 = load double, double* %13
%32 = load double*, double** %6
%33 = load i32, i32* %12
%34 = load i32, i32* %7
%35 = mul i32 %33, %34
%36 = zext i32 %35 to i64
%37 = getelementptr inbounds double, double* %32, i64 %36
store double %31, double* %37
br label %38
38: ; preds = %30
%39 = load i32*, i32** %10
%40 = getelementptr inbounds i32, i32* %39, i32 1
store i32* %40, i32** %10
%41 = load i32, i32* %39
store i32 %41, i32* %12
%42 = icmp ne i32 %41, -1
br i1 %42, label %30, label %43
43: ; preds = %38
br label %14
44: ; preds = %14
ret void
}

LLVM IR (-O2):
define void @scatter_double(double* noalias nocapture writeonly %0, i32 %1, double* noalias nocapture %2, i32 %3, i32* noalias nocapture %4) {
%6 = load i32, i32* %4
%7 = icmp eq i32 %6, -1
br i1 %7, label %30, label %11
8: ; preds = %21
%9 = load i32, i32* %27
%10 = icmp eq i32 %9, -1
br i1 %10, label %30, label %11
11: ; preds = %5, %8
%12 = phi i32 [ %9, %8 ], [ %6, %5 ]
%13 = phi i32* [ %27, %8 ], [ %4, %5 ]
%14 = getelementptr inbounds i32, i32* %13, i64 1
%15 = mul i32 %12, %3
%16 = zext i32 %15 to i64
%17 = getelementptr inbounds double, double* %2, i64 %16
%18 = load double, double* %17
%19 = getelementptr inbounds i32, i32* %13, i64 2
%20 = load i32, i32* %14
br label %21
21: ; preds = %21, %11
%22 = phi i32 [ %20, %11 ], [ %28, %21 ]
%23 = phi i32* [ %19, %11 ], [ %27, %21 ]
%24 = mul i32 %22, %1
%25 = zext i32 %24 to i64
%26 = getelementptr inbounds double, double* %0, i64 %25
store double %18, double* %26
%27 = getelementptr inbounds i32, i32* %23, i64 1
%28 = load i32, i32* %23
%29 = icmp eq i32 %28, -1
br i1 %29, label %8, label %21
30: ; preds = %8, %5
ret void
}