double generalized_vdC(int i, int base, int **p) {
  double h = 0.0, f, factor;
  int perm;
  int digit;
  f = factor = 1.0 / (double)base;
  while (i > 0) {
    digit = i % base;
    perm = p[base - 1][digit];
    h += (double)perm * factor;
    i /= base;
    factor *= f;
  }
  return h;
}


x86 assembly (clang, -O0):
<generalized_vdC>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %rdx,-0x10(%rbp)
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x18(%rbp)
cvtsi2sdl -0x8(%rbp),%xmm1
movsd  0xedd(%rip),%xmm0
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  %xmm0,-0x20(%rbp)
cmpl   $0x0,-0x4(%rbp)
jle    119c <generalized_vdC+0x9c>
mov    -0x4(%rbp),%eax
cltd
idivl  -0x8(%rbp)
mov    %edx,-0x30(%rbp)
mov    -0x10(%rbp),%rax
mov    -0x8(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
mov    (%rax,%rcx,4),%eax
mov    %eax,-0x2c(%rbp)
cvtsi2sdl -0x2c(%rbp),%xmm0
movsd  -0x28(%rbp),%xmm2
movsd  -0x18(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x18(%rbp)
mov    -0x8(%rbp),%ecx
mov    -0x4(%rbp),%eax
cltd
idiv   %ecx
mov    %eax,-0x4(%rbp)
movsd  -0x20(%rbp),%xmm0
mulsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
jmp    1131 <generalized_vdC+0x31>
movsd  -0x18(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<generalized_vdC>:
test   %edi,%edi
jle    114c <generalized_vdC+0x4c>
mov    %edi,%eax
cvtsi2sd %esi,%xmm0
movsd  0xeee(%rip),%xmm1
divsd  %xmm0,%xmm1
movslq %esi,%rcx
mov    -0x8(%rdx,%rcx,8),%rcx
xorpd  %xmm0,%xmm0
movapd %xmm1,%xmm2
cs nopw 0x0(%rax,%rax,1)
cltd
idiv   %esi
xorps  %xmm3,%xmm3
cvtsi2sdl (%rcx,%rdx,4),%xmm3
mulsd  %xmm2,%xmm3
addsd  %xmm3,%xmm0
mulsd  %xmm1,%xmm2
test   %eax,%eax
jg     1130 <generalized_vdC+0x30>
ret
xorps  %xmm0,%xmm0
ret

LLVM IR (-O0):
define double @generalized_vdC(i32 %0, i32 %1, i32** %2) {
%4 = alloca i32
%5 = alloca i32
%6 = alloca i32**
%7 = alloca double
%8 = alloca double
%9 = alloca double
%10 = alloca i32
%11 = alloca i32
store i32 %0, i32* %4
store i32 %1, i32* %5
store i32** %2, i32*** %6
store double 0.000000e+00, double* %7
%12 = load i32, i32* %5
%13 = sitofp i32 %12 to double
%14 = fdiv double 1.000000e+00, %13
store double %14, double* %9
store double %14, double* %8
br label %15
15: ; preds = %18, %3
%16 = load i32, i32* %4
%17 = icmp sgt i32 %16, 0
br i1 %17, label %18, label %43
18: ; preds = %15
%19 = load i32, i32* %4
%20 = load i32, i32* %5
%21 = srem i32 %19, %20
store i32 %21, i32* %11
%22 = load i32**, i32*** %6
%23 = load i32, i32* %5
%24 = sub nsw i32 %23, 1
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds i32*, i32** %22, i64 %25
%27 = load i32*, i32** %26
%28 = load i32, i32* %11
%29 = sext i32 %28 to i64
%30 = getelementptr inbounds i32, i32* %27, i64 %29
%31 = load i32, i32* %30
store i32 %31, i32* %10
%32 = load i32, i32* %10
%33 = sitofp i32 %32 to double
%34 = load double, double* %9
%35 = load double, double* %7
%36 = call double @llvm.fmuladd.f64(double %33, double %34, double %35)
store double %36, double* %7
%37 = load i32, i32* %5
%38 = load i32, i32* %4
%39 = sdiv i32 %38, %37
store i32 %39, i32* %4
%40 = load double, double* %8
%41 = load double, double* %9
%42 = fmul double %41, %40
store double %42, double* %9
br label %15
43: ; preds = %15
%44 = load double, double* %7
ret double %44
}

LLVM IR (-O2):
define double @generalized_vdC(i32 %0, i32 %1, i32** nocapture %2) {
%4 = sitofp i32 %1 to double
%5 = fdiv double 1.000000e+00, %4
%6 = icmp sgt i32 %0, 0
br i1 %6, label %7, label %25
7: ; preds = %3
%8 = add nsw i32 %1, -1
%9 = sext i32 %8 to i64
%10 = getelementptr inbounds i32*, i32** %2, i64 %9
%11 = load i32*, i32** %10
br label %12
12: ; preds = %7, %12
%13 = phi i32 [ %0, %7 ], [ %22, %12 ]
%14 = phi double [ 0.000000e+00, %7 ], [ %21, %12 ]
%15 = phi double [ %5, %7 ], [ %23, %12 ]
%16 = srem i32 %13, %1
%17 = zext i32 %16 to i64
%18 = getelementptr inbounds i32, i32* %11, i64 %17
%19 = load i32, i32* %18
%20 = sitofp i32 %19 to double
%21 = tail call double @llvm.fmuladd.f64(double %20, double %15, double %14)
%22 = sdiv i32 %13, %1
%23 = fmul double %5, %15
%24 = icmp sgt i32 %22, 0
br i1 %24, label %12, label %25
25: ; preds = %12, %3
%26 = phi double [ 0.000000e+00, %3 ], [ %21, %12 ]
ret double %26
}