void daxpy(double *restrict x, double *restrict y, double a, int n) {
  for (int i = 0; i < n; i++)
    y[i] = a * x[i] + y[i];
}


x86 assembly (clang, -O0):
<daxpy>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
movsd  %xmm0,-0x18(%rbp)
mov    %edx,-0x1c(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jge    1169 <daxpy+0x69>
movsd  -0x18(%rbp),%xmm0
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    111b <daxpy+0x1b>
pop    %rbp
ret

x86 assembly (clang, -O2):
<daxpy>:
test   %edx,%edx
jle    121c <daxpy+0x11c>
mov    %edx,%r9d
cmp    $0x4,%edx
jae    1117 <daxpy+0x17>
xor    %ecx,%ecx
jmp    1200 <daxpy+0x100>
mov    %r9d,%ecx
and    $0xfffffffc,%ecx
movapd %xmm0,%xmm1
unpcklpd %xmm0,%xmm1
lea    -0x4(%rcx),%rax
mov    %rax,%r8
shr    $0x2,%r8
add    $0x1,%r8
test   %rax,%rax
je     121d <daxpy+0x11d>
mov    %r8,%rax
and    $0xfffffffffffffffe,%rax
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
movupd (%rdi,%rdx,8),%xmm2
movupd 0x10(%rdi,%rdx,8),%xmm3
mulpd  %xmm1,%xmm2
movupd (%rsi,%rdx,8),%xmm4
addpd  %xmm2,%xmm4
movupd 0x10(%rsi,%rdx,8),%xmm2
movupd 0x20(%rsi,%rdx,8),%xmm5
movupd 0x30(%rsi,%rdx,8),%xmm6
mulpd  %xmm1,%xmm3
addpd  %xmm2,%xmm3
movupd %xmm4,(%rsi,%rdx,8)
movupd %xmm3,0x10(%rsi,%rdx,8)
movupd 0x20(%rdi,%rdx,8),%xmm2
movupd 0x30(%rdi,%rdx,8),%xmm3
mulpd  %xmm1,%xmm2
addpd  %xmm5,%xmm2
mulpd  %xmm1,%xmm3
addpd  %xmm6,%xmm3
movupd %xmm2,0x20(%rsi,%rdx,8)
movupd %xmm3,0x30(%rsi,%rdx,8)
add    $0x8,%rdx
add    $0xfffffffffffffffe,%rax
jne    1150 <daxpy+0x50>
test   $0x1,%r8b
je     11f6 <daxpy+0xf6>
movupd (%rdi,%rdx,8),%xmm2
movupd 0x10(%rdi,%rdx,8),%xmm3
movupd (%rsi,%rdx,8),%xmm4
movupd 0x10(%rsi,%rdx,8),%xmm5
mulpd  %xmm1,%xmm2
addpd  %xmm4,%xmm2
mulpd  %xmm1,%xmm3
addpd  %xmm5,%xmm3
movupd %xmm2,(%rsi,%rdx,8)
movupd %xmm3,0x10(%rsi,%rdx,8)
cmp    %r9,%rcx
je     121c <daxpy+0x11c>
nopl   0x0(%rax,%rax,1)
movsd  (%rdi,%rcx,8),%xmm1
mulsd  %xmm0,%xmm1
addsd  (%rsi,%rcx,8),%xmm1
movsd  %xmm1,(%rsi,%rcx,8)
add    $0x1,%rcx
cmp    %rcx,%r9
jne    1200 <daxpy+0x100>
ret
xor    %edx,%edx
test   $0x1,%r8b
jne    11c5 <daxpy+0xc5>
jmp    11f6 <daxpy+0xf6>

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

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