void retrend(double *source, int n, double *dest, double *slope,
             double *intercept) {
  int i;
  double y;
  for (i = 0; i < n; i++) {
    y = *slope * (double)i + *intercept;
    dest[i] = source[i] + y;
  }
}


x86 assembly (clang, -O0):
<retrend>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
movl   $0x0,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    1179 <retrend+0x79>
mov    -0x20(%rbp),%rax
movsd  (%rax),%xmm0
cvtsi2sdl -0x2c(%rbp),%xmm2
mov    -0x28(%rbp),%rax
movsd  (%rax),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
addsd  -0x38(%rbp),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x2c(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    111e <retrend+0x1e>
pop    %rbp
ret

x86 assembly (clang, -O2):
<retrend>:
push   %rbp
push   %r14
push   %rbx
test   %esi,%esi
jle    1272 <retrend+0x172>
mov    %esi,%r9d
cmp    $0x4,%esi
jae    111b <retrend+0x1b>
xor    %esi,%esi
jmp    1200 <retrend+0x100>
lea    0x8(%rcx),%rax
cmp    %rdx,%rax
seta   %r14b
lea    (%rdx,%r9,8),%rsi
cmp    %rcx,%rsi
seta   %bl
lea    0x8(%r8),%rax
cmp    %rdx,%rax
seta   %al
lea    (%rdi,%r9,8),%rbp
cmp    %r8,%rsi
seta   %r11b
cmp    %rdx,%rbp
seta   %r10b
cmp    %rdi,%rsi
seta   %bpl
xor    %esi,%esi
test   %bl,%r14b
jne    1200 <retrend+0x100>
and    %r11b,%al
jne    1200 <retrend+0x100>
and    %bpl,%r10b
jne    1200 <retrend+0x100>
mov    %r9d,%esi
and    $0xfffffffc,%esi
movsd  (%rcx),%xmm0
unpcklpd %xmm0,%xmm0
movsd  (%r8),%xmm1
unpcklpd %xmm1,%xmm1
lea    0x0(,%r9,8),%r10
and    $0xffffffffffffffe0,%r10
movdqa 0xe65(%rip),%xmm2
xor    %eax,%eax
movdqa 0xe6b(%rip),%xmm3
movdqa 0xe73(%rip),%xmm4
nopl   (%rax)
movdqa %xmm2,%xmm5
cvtdq2pd %xmm2,%xmm6
paddd  %xmm3,%xmm5
cvtdq2pd %xmm5,%xmm5
mulpd  %xmm0,%xmm6
addpd  %xmm1,%xmm6
mulpd  %xmm0,%xmm5
addpd  %xmm1,%xmm5
movupd (%rdi,%rax,1),%xmm7
addpd  %xmm6,%xmm7
movupd 0x10(%rdi,%rax,1),%xmm6
addpd  %xmm5,%xmm6
movupd %xmm7,(%rdx,%rax,1)
movupd %xmm6,0x10(%rdx,%rax,1)
paddd  %xmm4,%xmm2
add    $0x20,%rax
cmp    %rax,%r10
jne    11b0 <retrend+0xb0>
cmp    %r9,%rsi
je     1272 <retrend+0x172>
mov    %rsi,%rax
not    %rax
test   $0x1,%r9b
je     122a <retrend+0x12a>
xorps  %xmm0,%xmm0
cvtsi2sd %esi,%xmm0
mulsd  (%rcx),%xmm0
addsd  (%r8),%xmm0
addsd  (%rdi,%rsi,8),%xmm0
movsd  %xmm0,(%rdx,%rsi,8)
or     $0x1,%rsi
add    %r9,%rax
je     1272 <retrend+0x172>
nop
xorps  %xmm0,%xmm0
cvtsi2sd %esi,%xmm0
mulsd  (%rcx),%xmm0
addsd  (%r8),%xmm0
addsd  (%rdi,%rsi,8),%xmm0
movsd  %xmm0,(%rdx,%rsi,8)
lea    0x1(%rsi),%eax
xorps  %xmm0,%xmm0
cvtsi2sd %eax,%xmm0
mulsd  (%rcx),%xmm0
addsd  (%r8),%xmm0
addsd  0x8(%rdi,%rsi,8),%xmm0
movsd  %xmm0,0x8(%rdx,%rsi,8)
add    $0x2,%rsi
cmp    %r9,%rsi
jne    1230 <retrend+0x130>
pop    %rbx
pop    %r14
pop    %rbp
ret

LLVM IR (-O0):
define void @retrend(double* %0, i32 %1, double* %2, double* %3, double* %4) {
%6 = alloca double*
%7 = alloca i32
%8 = alloca double*
%9 = alloca double*
%10 = alloca double*
%11 = alloca i32
%12 = alloca double
store double* %0, double** %6
store i32 %1, i32* %7
store double* %2, double** %8
store double* %3, double** %9
store double* %4, double** %10
store i32 0, i32* %11
br label %13
13: ; preds = %36, %5
%14 = load i32, i32* %11
%15 = load i32, i32* %7
%16 = icmp slt i32 %14, %15
br i1 %16, label %17, label %39
17: ; preds = %13
%18 = load double*, double** %9
%19 = load double, double* %18
%20 = load i32, i32* %11
%21 = sitofp i32 %20 to double
%22 = load double*, double** %10
%23 = load double, double* %22
%24 = call double @llvm.fmuladd.f64(double %19, double %21, double %23)
store double %24, double* %12
%25 = load double*, double** %6
%26 = load i32, i32* %11
%27 = sext i32 %26 to i64
%28 = getelementptr inbounds double, double* %25, i64 %27
%29 = load double, double* %28
%30 = load double, double* %12
%31 = fadd double %29, %30
%32 = load double*, double** %8
%33 = load i32, i32* %11
%34 = sext i32 %33 to i64
%35 = getelementptr inbounds double, double* %32, i64 %34
store double %31, double* %35
br label %36
36: ; preds = %17
%37 = load i32, i32* %11
%38 = add nsw i32 %37, 1
store i32 %38, i32* %11
br label %13
39: ; preds = %13
ret void
}

LLVM IR (-O2):
define void @retrend(double* nocapture %0, i32 %1, double* nocapture writeonly %2, double* nocapture %3, double* nocapture %4) {
%6 = icmp sgt i32 %1, 0
br i1 %6, label %7, label %106
7: ; preds = %5
%8 = zext i32 %1 to i64
%9 = icmp ult i32 %1, 4
br i1 %9, label %63, label %10
10: ; preds = %7
%11 = getelementptr double, double* %2, i64 %8
%12 = getelementptr double, double* %3, i64 1
%13 = getelementptr double, double* %4, i64 1
%14 = getelementptr double, double* %0, i64 %8
%15 = icmp ugt double* %12, %2
%16 = icmp ugt double* %11, %3
%17 = and i1 %15, %16
%18 = icmp ugt double* %13, %2
%19 = icmp ugt double* %11, %4
%20 = and i1 %18, %19
%21 = or i1 %17, %20
%22 = icmp ugt double* %14, %2
%23 = icmp ugt double* %11, %0
%24 = and i1 %22, %23
%25 = or i1 %21, %24
br i1 %25, label %63, label %26
26: ; preds = %10
%27 = and i64 %8, 4294967292
%28 = load double, double* %3
%29 = insertelement <2 x double> poison, double %28, i64 0
%30 = shufflevector <2 x double> %29, <2 x double> poison, <2 x i32> zeroinitializer
%31 = insertelement <2 x double> poison, double %28, i64 0
%32 = shufflevector <2 x double> %31, <2 x double> poison, <2 x i32> zeroinitializer
%33 = load double, double* %4
%34 = insertelement <2 x double> poison, double %33, i64 0
%35 = shufflevector <2 x double> %34, <2 x double> poison, <2 x i32> zeroinitializer
%36 = insertelement <2 x double> poison, double %33, i64 0
%37 = shufflevector <2 x double> %36, <2 x double> poison, <2 x i32> zeroinitializer
br label %38
38: ; preds = %38, %26
%39 = phi i64 [ 0, %26 ], [ %58, %38 ]
%40 = phi <2 x i32> [ <i32 0, i32 1>, %26 ], [ %59, %38 ]
%41 = add <2 x i32> %40, <i32 2, i32 2>
%42 = sitofp <2 x i32> %40 to <2 x double>
%43 = sitofp <2 x i32> %41 to <2 x double>
%44 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %30, <2 x double> %42, <2 x double> %35)
%45 = call <2 x double> @llvm.fmuladd.v2f64(<2 x double> %32, <2 x double> %43, <2 x double> %37)
%46 = getelementptr inbounds double, double* %0, i64 %39
%47 = bitcast double* %46 to <2 x double>*
%48 = load <2 x double>, <2 x double>* %47
%49 = getelementptr inbounds double, double* %46, i64 2
%50 = bitcast double* %49 to <2 x double>*
%51 = load <2 x double>, <2 x double>* %50
%52 = fadd <2 x double> %48, %44
%53 = fadd <2 x double> %51, %45
%54 = getelementptr inbounds double, double* %2, i64 %39
%55 = bitcast double* %54 to <2 x double>*
store <2 x double> %52, <2 x double>* %55
%56 = getelementptr inbounds double, double* %54, i64 2
%57 = bitcast double* %56 to <2 x double>*
store <2 x double> %53, <2 x double>* %57
%58 = add nuw i64 %39, 4
%59 = add <2 x i32> %40, <i32 4, i32 4>
%60 = icmp eq i64 %58, %27
br i1 %60, label %61, label %38
61: ; preds = %38
%62 = icmp eq i64 %27, %8
br i1 %62, label %106, label %63
63: ; preds = %10, %7, %61
%64 = phi i64 [ 0, %10 ], [ 0, %7 ], [ %27, %61 ]
%65 = xor i64 %64, -1
%66 = and i64 %8, 1
%67 = icmp eq i64 %66, 0
br i1 %67, label %79, label %68
68: ; preds = %63
%69 = load double, double* %3
%70 = trunc i64 %64 to i32
%71 = sitofp i32 %70 to double
%72 = load double, double* %4
%73 = tail call double @llvm.fmuladd.f64(double %69, double %71, double %72)
%74 = getelementptr inbounds double, double* %0, i64 %64
%75 = load double, double* %74
%76 = fadd double %75, %73
%77 = getelementptr inbounds double, double* %2, i64 %64
store double %76, double* %77
%78 = or i64 %64, 1
br label %79
79: ; preds = %68, %63
%80 = phi i64 [ %64, %63 ], [ %78, %68 ]
%81 = sub nsw i64 0, %8
%82 = icmp eq i64 %65, %81
br i1 %82, label %106, label %83
83: ; preds = %79, %83
%84 = phi i64 [ %104, %83 ], [ %80, %79 ]
%85 = load double, double* %3
%86 = trunc i64 %84 to i32
%87 = sitofp i32 %86 to double
%88 = load double, double* %4
%89 = tail call double @llvm.fmuladd.f64(double %85, double %87, double %88)
%90 = getelementptr inbounds double, double* %0, i64 %84
%91 = load double, double* %90
%92 = fadd double %91, %89
%93 = getelementptr inbounds double, double* %2, i64 %84
store double %92, double* %93
%94 = add nuw nsw i64 %84, 1
%95 = load double, double* %3
%96 = trunc i64 %94 to i32
%97 = sitofp i32 %96 to double
%98 = load double, double* %4
%99 = tail call double @llvm.fmuladd.f64(double %95, double %97, double %98)
%100 = getelementptr inbounds double, double* %0, i64 %94
%101 = load double, double* %100
%102 = fadd double %101, %99
%103 = getelementptr inbounds double, double* %2, i64 %94
store double %102, double* %103
%104 = add nuw nsw i64 %84, 2
%105 = icmp eq i64 %104, %8
br i1 %105, label %106, label %83
106: ; preds = %79, %83, %61, %5
ret void
}