void PT_mac_sub(double *sum, double *p1, double *p2, int n) {
  int i;
  for (i = 0; i < n; i++) {
    sum[i] -= p1[i] * p2[i];
  }
}


x86 assembly (clang, -O0):
<PT_mac_sub>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0x20(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jge    117f <PT_mac_sub+0x7f>
mov    -0x10(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
mov    -0x8(%rbp),%rax
movslq -0x20(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
movq   %xmm0,%rdx
movabs $0x8000000000000000,%rsi
xor    %rsi,%rdx
movq   %rdx,%xmm0
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x20(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x20(%rbp)
jmp    111a <PT_mac_sub+0x1a>
pop    %rbp
ret

x86 assembly (clang, -O2):
<PT_mac_sub>:
test   %ecx,%ecx
jle    121d <PT_mac_sub+0x11d>
mov    %ecx,%r8d
cmp    $0x4,%ecx
jae    1117 <PT_mac_sub+0x17>
xor    %ecx,%ecx
jmp    11aa <PT_mac_sub+0xaa>
lea    (%rdi,%r8,8),%rcx
lea    (%rsi,%r8,8),%rax
cmp    %rdi,%rax
seta   %r10b
lea    (%rdx,%r8,8),%rax
cmp    %rsi,%rcx
seta   %r11b
cmp    %rdi,%rax
seta   %al
cmp    %rdx,%rcx
seta   %r9b
xor    %ecx,%ecx
test   %r11b,%r10b
jne    11aa <PT_mac_sub+0xaa>
and    %r9b,%al
jne    11aa <PT_mac_sub+0xaa>
mov    %r8d,%ecx
and    $0xfffffffc,%ecx
lea    0x0(,%r8,8),%r9
and    $0xffffffffffffffe0,%r9
xor    %eax,%eax
xchg   %ax,%ax
movupd (%rsi,%rax,1),%xmm0
movupd 0x10(%rsi,%rax,1),%xmm1
movupd (%rdx,%rax,1),%xmm2
mulpd  %xmm0,%xmm2
movupd 0x10(%rdx,%rax,1),%xmm0
mulpd  %xmm1,%xmm0
movupd (%rdi,%rax,1),%xmm1
subpd  %xmm2,%xmm1
movupd 0x10(%rdi,%rax,1),%xmm2
subpd  %xmm0,%xmm2
movupd %xmm1,(%rdi,%rax,1)
movupd %xmm2,0x10(%rdi,%rax,1)
add    $0x20,%rax
cmp    %rax,%r9
jne    1160 <PT_mac_sub+0x60>
cmp    %r8,%rcx
je     121d <PT_mac_sub+0x11d>
mov    %rcx,%rax
not    %rax
test   $0x1,%r8b
je     11d2 <PT_mac_sub+0xd2>
movsd  (%rsi,%rcx,8),%xmm0
mulsd  (%rdx,%rcx,8),%xmm0
movsd  (%rdi,%rcx,8),%xmm1
subsd  %xmm0,%xmm1
movsd  %xmm1,(%rdi,%rcx,8)
or     $0x1,%rcx
add    %r8,%rax
je     121d <PT_mac_sub+0x11d>
nopw   0x0(%rax,%rax,1)
movsd  (%rsi,%rcx,8),%xmm0
mulsd  (%rdx,%rcx,8),%xmm0
movsd  (%rdi,%rcx,8),%xmm1
subsd  %xmm0,%xmm1
movsd  0x8(%rdi,%rcx,8),%xmm0
movsd  %xmm1,(%rdi,%rcx,8)
movsd  0x8(%rsi,%rcx,8),%xmm1
mulsd  0x8(%rdx,%rcx,8),%xmm1
subsd  %xmm1,%xmm0
movsd  %xmm0,0x8(%rdi,%rcx,8)
add    $0x2,%rcx
cmp    %rcx,%r8
jne    11e0 <PT_mac_sub+0xe0>
ret

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

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