void OuterProduct(double *pV1, double *pV2, int m, int n, double *pM1) {
  for (int i = 0; i <= m - 1; i = i + 1) {
    for (int j = 0; j <= n - 1; j = j + 1) {
      *(pM1 + i * n + j) = *(pV1 + i) * (*(pV2 + j));
    }
  }
}


x86 assembly (clang, -O0):
<OuterProduct>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %ecx,-0x18(%rbp)
mov    %r8,-0x20(%rbp)
movl   $0x0,-0x24(%rbp)
mov    -0x24(%rbp),%eax
mov    -0x14(%rbp),%ecx
sub    $0x1,%ecx
cmp    %ecx,%eax
jg     119f <OuterProduct+0x9f>
movl   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%eax
mov    -0x18(%rbp),%ecx
sub    $0x1,%ecx
cmp    %ecx,%eax
jg     118c <OuterProduct+0x8c>
mov    -0x8(%rbp),%rax
movslq -0x24(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x10(%rbp),%rax
movslq -0x28(%rbp),%rcx
mulsd  (%rax,%rcx,8),%xmm0
mov    -0x20(%rbp),%rax
mov    -0x24(%rbp),%ecx
imul   -0x18(%rbp),%ecx
movslq %ecx,%rcx
shl    $0x3,%rcx
add    %rcx,%rax
movslq -0x28(%rbp),%rcx
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    1135 <OuterProduct+0x35>
jmp    1191 <OuterProduct+0x91>
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    111d <OuterProduct+0x1d>
pop    %rbp
ret

x86 assembly (clang, -O2):
<OuterProduct>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    %r8,-0x38(%rsp)
test   %edx,%edx
jle    136e <OuterProduct+0x26e>
movslq %ecx,%rbp
mov    %edx,%r13d
mov    %ebp,%eax
lea    (%rsi,%rax,8),%rdx
mov    %rdx,-0x10(%rsp)
mov    %eax,%edx
and    $0xfffffffc,%edx
mov    %rdx,-0x18(%rsp)
add    $0xfffffffffffffffc,%rdx
mov    %rdx,-0x20(%rsp)
mov    %rdx,%rbx
shr    $0x2,%rbx
add    $0x1,%rbx
mov    %rbx,%rdx
mov    %rbx,-0x28(%rsp)
and    $0xfffffffffffffffe,%rbx
mov    %rbx,-0x30(%rsp)
mov    %eax,%r9d
and    $0x3,%r9d
mov    -0x38(%rsp),%r8
lea    0x30(%r8),%rdx
mov    %rbp,-0x8(%rsp)
lea    0x0(,%rbp,8),%r12
xor    %r15d,%r15d
jmp    1193 <OuterProduct+0x93>
nopl   0x0(%rax)
add    $0x1,%r15
add    %r12,%rdx
add    %r12,%r8
cmp    %r13,%r15
je     136e <OuterProduct+0x26e>
test   %ecx,%ecx
jle    1180 <OuterProduct+0x80>
cmp    $0x4,%ecx
jb     12b0 <OuterProduct+0x1b0>
mov    %r15,%rbp
imul   -0x8(%rsp),%rbp
mov    -0x38(%rsp),%rbx
lea    (%rbx,%rbp,8),%r10
add    %rax,%rbp
lea    (%rbx,%rbp,8),%rbp
lea    (%rdi,%r15,8),%r11
lea    (%rdi,%r15,8),%rbx
add    $0x8,%rbx
cmp    %rbx,%r10
setb   %r14b
cmp    %rbp,%r11
setb   %r11b
cmp    -0x10(%rsp),%r10
setb   %bl
cmp    %rsi,%rbp
seta   %bpl
test   %r11b,%r14b
jne    12b0 <OuterProduct+0x1b0>
mov    $0x0,%r11d
and    %bpl,%bl
jne    12b3 <OuterProduct+0x1b3>
cmpq   $0x0,-0x20(%rsp)
je     135c <OuterProduct+0x25c>
movsd  (%rdi,%r15,8),%xmm0
unpcklpd %xmm0,%xmm0
mov    -0x30(%rsp),%rbp
xor    %ebx,%ebx
nopw   0x0(%rax,%rax,1)
movupd (%rsi,%rbx,8),%xmm1
movupd 0x10(%rsi,%rbx,8),%xmm2
mulpd  %xmm0,%xmm1
mulpd  %xmm0,%xmm2
movupd %xmm1,-0x30(%rdx,%rbx,8)
movupd %xmm2,-0x20(%rdx,%rbx,8)
movupd 0x20(%rsi,%rbx,8),%xmm1
movupd 0x30(%rsi,%rbx,8),%xmm2
mulpd  %xmm0,%xmm1
mulpd  %xmm0,%xmm2
movupd %xmm1,-0x10(%rdx,%rbx,8)
movupd %xmm2,(%rdx,%rbx,8)
add    $0x8,%rbx
add    $0xfffffffffffffffe,%rbp
jne    1220 <OuterProduct+0x120>
testb  $0x1,-0x28(%rsp)
je     1299 <OuterProduct+0x199>
movsd  (%rdi,%r15,8),%xmm0
unpcklpd %xmm0,%xmm0
movupd (%rsi,%rbx,8),%xmm1
movupd 0x10(%rsi,%rbx,8),%xmm2
mulpd  %xmm0,%xmm1
mulpd  %xmm0,%xmm2
movupd %xmm1,(%r10,%rbx,8)
movupd %xmm2,0x10(%r10,%rbx,8)
mov    -0x18(%rsp),%rbp
mov    %rbp,%r11
cmp    %rax,%rbp
je     1180 <OuterProduct+0x80>
jmp    12b3 <OuterProduct+0x1b3>
nopl   0x0(%rax)
xor    %r11d,%r11d
mov    %r11,%rbx
not    %rbx
add    %rax,%rbx
test   %r9,%r9
je     12ec <OuterProduct+0x1ec>
mov    %r9,%rbp
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movsd  (%rdi,%r15,8),%xmm0
mulsd  (%rsi,%r11,8),%xmm0
movsd  %xmm0,(%r8,%r11,8)
add    $0x1,%r11
add    $0xffffffffffffffff,%rbp
jne    12d0 <OuterProduct+0x1d0>
cmp    $0x3,%rbx
jb     1180 <OuterProduct+0x80>
cs nopw 0x0(%rax,%rax,1)
movsd  (%rdi,%r15,8),%xmm0
mulsd  (%rsi,%r11,8),%xmm0
movsd  %xmm0,(%r8,%r11,8)
movsd  (%rdi,%r15,8),%xmm0
mulsd  0x8(%rsi,%r11,8),%xmm0
movsd  %xmm0,0x8(%r8,%r11,8)
movsd  (%rdi,%r15,8),%xmm0
mulsd  0x10(%rsi,%r11,8),%xmm0
movsd  %xmm0,0x10(%r8,%r11,8)
movsd  (%rdi,%r15,8),%xmm0
mulsd  0x18(%rsi,%r11,8),%xmm0
movsd  %xmm0,0x18(%r8,%r11,8)
add    $0x4,%r11
cmp    %r11,%rax
jne    1300 <OuterProduct+0x200>
jmp    1180 <OuterProduct+0x80>
xor    %ebx,%ebx
testb  $0x1,-0x28(%rsp)
jne    126f <OuterProduct+0x16f>
jmp    1299 <OuterProduct+0x199>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @OuterProduct(double* %0, double* %1, i32 %2, i32 %3, double* %4) {
%6 = alloca double*
%7 = alloca double*
%8 = alloca i32
%9 = alloca i32
%10 = alloca double*
%11 = alloca i32
%12 = alloca i32
store double* %0, double** %6
store double* %1, double** %7
store i32 %2, i32* %8
store i32 %3, i32* %9
store double* %4, double** %10
store i32 0, i32* %11
br label %13
13: ; preds = %49, %5
%14 = load i32, i32* %11
%15 = load i32, i32* %8
%16 = sub nsw i32 %15, 1
%17 = icmp sle i32 %14, %16
br i1 %17, label %18, label %52
18: ; preds = %13
store i32 0, i32* %12
br label %19
19: ; preds = %45, %18
%20 = load i32, i32* %12
%21 = load i32, i32* %9
%22 = sub nsw i32 %21, 1
%23 = icmp sle i32 %20, %22
br i1 %23, label %24, label %48
24: ; preds = %19
%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** %7
%31 = load i32, i32* %12
%32 = sext i32 %31 to i64
%33 = getelementptr inbounds double, double* %30, i64 %32
%34 = load double, double* %33
%35 = fmul double %29, %34
%36 = load double*, double** %10
%37 = load i32, i32* %11
%38 = load i32, i32* %9
%39 = mul nsw i32 %37, %38
%40 = sext i32 %39 to i64
%41 = getelementptr inbounds double, double* %36, i64 %40
%42 = load i32, i32* %12
%43 = sext i32 %42 to i64
%44 = getelementptr inbounds double, double* %41, i64 %43
store double %35, double* %44
br label %45
45: ; preds = %24
%46 = load i32, i32* %12
%47 = add nsw i32 %46, 1
store i32 %47, i32* %12
br label %19
48: ; preds = %19
br label %49
49: ; preds = %48
%50 = load i32, i32* %11
%51 = add nsw i32 %50, 1
store i32 %51, i32* %11
br label %13
52: ; preds = %13
ret void
}

LLVM IR (-O2):
define void @OuterProduct(double* nocapture %0, double* nocapture %1, i32 %2, i32 %3, double* nocapture writeonly %4) {
%6 = icmp sgt i32 %2, 0
br i1 %6, label %7, label %129
7: ; preds = %5
%8 = icmp sgt i32 %3, 0
%9 = sext i32 %3 to i64
%10 = zext i32 %2 to i64
%11 = zext i32 %3 to i64
%12 = getelementptr double, double* %1, i64 %11
%13 = and i64 %11, 4294967292
%14 = add nsw i64 %13, -4
%15 = lshr exact i64 %14, 2
%16 = add nuw nsw i64 %15, 1
%17 = icmp ult i32 %3, 4
%18 = and i64 %11, 4294967292
%19 = and i64 %16, 1
%20 = icmp eq i64 %14, 0
%21 = and i64 %16, 9223372036854775806
%22 = icmp eq i64 %19, 0
%23 = icmp eq i64 %18, %11
%24 = and i64 %11, 3
%25 = icmp eq i64 %24, 0
br label %26
26: ; preds = %7, %130
%27 = phi i64 [ 0, %7 ], [ %131, %130 ]
%28 = mul i64 %27, %9
%29 = getelementptr double, double* %4, i64 %28
%30 = add i64 %28, %11
%31 = getelementptr double, double* %4, i64 %30
%32 = getelementptr double, double* %0, i64 %27
%33 = add nuw i64 %27, 1
%34 = getelementptr double, double* %0, i64 %33
br i1 %8, label %35, label %130
35: ; preds = %26
%36 = getelementptr inbounds double, double* %0, i64 %27
%37 = mul nsw i64 %27, %9
%38 = getelementptr inbounds double, double* %4, i64 %37
br i1 %17, label %111, label %39
39: ; preds = %35
%40 = icmp ult double* %29, %34
%41 = icmp ult double* %32, %31
%42 = and i1 %40, %41
%43 = icmp ult double* %29, %12
%44 = icmp ugt double* %31, %1
%45 = and i1 %43, %44
%46 = or i1 %42, %45
br i1 %46, label %111, label %47
47: ; preds = %39
br i1 %20, label %90, label %48
48: ; preds = %47
%49 = load double, double* %36
%50 = insertelement <2 x double> poison, double %49, i64 0
%51 = shufflevector <2 x double> %50, <2 x double> poison, <2 x i32> zeroinitializer
%52 = insertelement <2 x double> poison, double %49, i64 0
%53 = shufflevector <2 x double> %52, <2 x double> poison, <2 x i32> zeroinitializer
%54 = load double, double* %36
%55 = insertelement <2 x double> poison, double %54, i64 0
%56 = shufflevector <2 x double> %55, <2 x double> poison, <2 x i32> zeroinitializer
%57 = insertelement <2 x double> poison, double %54, i64 0
%58 = shufflevector <2 x double> %57, <2 x double> poison, <2 x i32> zeroinitializer
br label %59
59: ; preds = %59, %48
%60 = phi i64 [ 0, %48 ], [ %87, %59 ]
%61 = phi i64 [ 0, %48 ], [ %88, %59 ]
%62 = getelementptr inbounds double, double* %1, i64 %60
%63 = bitcast double* %62 to <2 x double>*
%64 = load <2 x double>, <2 x double>* %63
%65 = getelementptr inbounds double, double* %62, i64 2
%66 = bitcast double* %65 to <2 x double>*
%67 = load <2 x double>, <2 x double>* %66
%68 = fmul <2 x double> %51, %64
%69 = fmul <2 x double> %53, %67
%70 = getelementptr inbounds double, double* %38, i64 %60
%71 = bitcast double* %70 to <2 x double>*
store <2 x double> %68, <2 x double>* %71
%72 = getelementptr inbounds double, double* %70, i64 2
%73 = bitcast double* %72 to <2 x double>*
store <2 x double> %69, <2 x double>* %73
%74 = or i64 %60, 4
%75 = getelementptr inbounds double, double* %1, i64 %74
%76 = bitcast double* %75 to <2 x double>*
%77 = load <2 x double>, <2 x double>* %76
%78 = getelementptr inbounds double, double* %75, i64 2
%79 = bitcast double* %78 to <2 x double>*
%80 = load <2 x double>, <2 x double>* %79
%81 = fmul <2 x double> %56, %77
%82 = fmul <2 x double> %58, %80
%83 = getelementptr inbounds double, double* %38, i64 %74
%84 = bitcast double* %83 to <2 x double>*
store <2 x double> %81, <2 x double>* %84
%85 = getelementptr inbounds double, double* %83, i64 2
%86 = bitcast double* %85 to <2 x double>*
store <2 x double> %82, <2 x double>* %86
%87 = add nuw i64 %60, 8
%88 = add i64 %61, 2
%89 = icmp eq i64 %88, %21
br i1 %89, label %90, label %59
90: ; preds = %59, %47
%91 = phi i64 [ 0, %47 ], [ %87, %59 ]
br i1 %22, label %110, label %92
92: ; preds = %90
%93 = load double, double* %36
%94 = insertelement <2 x double> poison, double %93, i64 0
%95 = shufflevector <2 x double> %94, <2 x double> poison, <2 x i32> zeroinitializer
%96 = insertelement <2 x double> poison, double %93, i64 0
%97 = shufflevector <2 x double> %96, <2 x double> poison, <2 x i32> zeroinitializer
%98 = getelementptr inbounds double, double* %1, i64 %91
%99 = bitcast double* %98 to <2 x double>*
%100 = load <2 x double>, <2 x double>* %99
%101 = getelementptr inbounds double, double* %98, i64 2
%102 = bitcast double* %101 to <2 x double>*
%103 = load <2 x double>, <2 x double>* %102
%104 = fmul <2 x double> %95, %100
%105 = fmul <2 x double> %97, %103
%106 = getelementptr inbounds double, double* %38, i64 %91
%107 = bitcast double* %106 to <2 x double>*
store <2 x double> %104, <2 x double>* %107
%108 = getelementptr inbounds double, double* %106, i64 2
%109 = bitcast double* %108 to <2 x double>*
store <2 x double> %105, <2 x double>* %109
br label %110
110: ; preds = %90, %92
br i1 %23, label %130, label %111
111: ; preds = %39, %35, %110
%112 = phi i64 [ 0, %39 ], [ 0, %35 ], [ %18, %110 ]
%113 = xor i64 %112, -1
%114 = add nsw i64 %113, %11
br i1 %25, label %126, label %115
115: ; preds = %111, %115
%116 = phi i64 [ %123, %115 ], [ %112, %111 ]
%117 = phi i64 [ %124, %115 ], [ 0, %111 ]
%118 = load double, double* %36
%119 = getelementptr inbounds double, double* %1, i64 %116
%120 = load double, double* %119
%121 = fmul double %118, %120
%122 = getelementptr inbounds double, double* %38, i64 %116
store double %121, double* %122
%123 = add nuw nsw i64 %116, 1
%124 = add i64 %117, 1
%125 = icmp eq i64 %124, %24
br i1 %125, label %126, label %115
126: ; preds = %115, %111
%127 = phi i64 [ %112, %111 ], [ %123, %115 ]
%128 = icmp ult i64 %114, 3
br i1 %128, label %130, label %133
129: ; preds = %130, %5
ret void
130: ; preds = %126, %133, %110, %26
%131 = add nuw nsw i64 %27, 1
%132 = icmp eq i64 %131, %10
br i1 %132, label %129, label %26
133: ; preds = %126, %133
%134 = phi i64 [ %158, %133 ], [ %127, %126 ]
%135 = load double, double* %36
%136 = getelementptr inbounds double, double* %1, i64 %134
%137 = load double, double* %136
%138 = fmul double %135, %137
%139 = getelementptr inbounds double, double* %38, i64 %134
store double %138, double* %139
%140 = add nuw nsw i64 %134, 1
%141 = load double, double* %36
%142 = getelementptr inbounds double, double* %1, i64 %140
%143 = load double, double* %142
%144 = fmul double %141, %143
%145 = getelementptr inbounds double, double* %38, i64 %140
store double %144, double* %145
%146 = add nuw nsw i64 %134, 2
%147 = load double, double* %36
%148 = getelementptr inbounds double, double* %1, i64 %146
%149 = load double, double* %148
%150 = fmul double %147, %149
%151 = getelementptr inbounds double, double* %38, i64 %146
store double %150, double* %151
%152 = add nuw nsw i64 %134, 3
%153 = load double, double* %36
%154 = getelementptr inbounds double, double* %1, i64 %152
%155 = load double, double* %154
%156 = fmul double %153, %155
%157 = getelementptr inbounds double, double* %38, i64 %152
store double %156, double* %157
%158 = add nuw nsw i64 %134, 4
%159 = icmp eq i64 %158, %11
br i1 %159, label %130, label %133
}