unsigned long long largestProductHorizontallyAndVertically(int grid[20][20]) {
  unsigned long long productHorizontal;
  unsigned long long productVertical;
  unsigned long long largest = 1;
  for (int i = 0; i < 20 - 4; i++) {
    for (int j = 0; j < 20 - 4; j++) {
      productHorizontal = productVertical = 1;
      for (int k = j; k < j + 4; k++) {
        if (k < 0 || k >= 20)
          continue;
        productHorizontal *= grid[i][k];
        productVertical *= grid[k][i];
      }
      largest =
          ((productHorizontal > largest ? productHorizontal : largest) >
                   productVertical
               ? (productHorizontal > largest ? productHorizontal : largest)
               : productVertical);
    }
  }
  return largest;
}


x86 assembly (clang, -O0):
<largestProductHorizontallyAndVertically>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
movq   $0x1,-0x20(%rbp)
movl   $0x0,-0x24(%rbp)
cmpl   $0x10,-0x24(%rbp)
jge    1252 <largestProductHorizontallyAndVertically+0x152>
movl   $0x0,-0x28(%rbp)
cmpl   $0x10,-0x28(%rbp)
jge    123f <largestProductHorizontallyAndVertically+0x13f>
movq   $0x1,-0x18(%rbp)
movq   $0x1,-0x10(%rbp)
mov    -0x28(%rbp),%eax
mov    %eax,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    -0x28(%rbp),%ecx
add    $0x4,%ecx
cmp    %ecx,%eax
jge    11c0 <largestProductHorizontallyAndVertically+0xc0>
cmpl   $0x0,-0x2c(%rbp)
jl     116d <largestProductHorizontallyAndVertically+0x6d>
cmpl   $0x14,-0x2c(%rbp)
jl     1172 <largestProductHorizontallyAndVertically+0x72>
jmp    11b2 <largestProductHorizontallyAndVertically+0xb2>
mov    -0x8(%rbp),%rax
movslq -0x24(%rbp),%rcx
imul   $0x50,%rcx,%rcx
add    %rcx,%rax
movslq -0x2c(%rbp),%rcx
movslq (%rax,%rcx,4),%rax
imul   -0x10(%rbp),%rax
mov    %rax,-0x10(%rbp)
mov    -0x8(%rbp),%rax
movslq -0x2c(%rbp),%rcx
imul   $0x50,%rcx,%rcx
add    %rcx,%rax
movslq -0x24(%rbp),%rcx
movslq (%rax,%rcx,4),%rax
imul   -0x18(%rbp),%rax
mov    %rax,-0x18(%rbp)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1148 <largestProductHorizontallyAndVertically+0x48>
mov    -0x10(%rbp),%rax
cmp    -0x20(%rbp),%rax
jbe    11db <largestProductHorizontallyAndVertically+0xdb>
mov    -0x10(%rbp),%rax
mov    %rax,-0x38(%rbp)
jmp    11e3 <largestProductHorizontallyAndVertically+0xe3>
mov    -0x20(%rbp),%rax
mov    %rax,-0x38(%rbp)
mov    -0x38(%rbp),%rax
cmp    -0x18(%rbp),%rax
jbe    1221 <largestProductHorizontallyAndVertically+0x121>
mov    -0x10(%rbp),%rax
cmp    -0x20(%rbp),%rax
jbe    120c <largestProductHorizontallyAndVertically+0x10c>
mov    -0x10(%rbp),%rax
mov    %rax,-0x40(%rbp)
jmp    1214 <largestProductHorizontallyAndVertically+0x114>
mov    -0x20(%rbp),%rax
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rax
mov    %rax,-0x48(%rbp)
jmp    1229 <largestProductHorizontallyAndVertically+0x129>
mov    -0x18(%rbp),%rax
mov    %rax,-0x48(%rbp)
mov    -0x48(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    1128 <largestProductHorizontallyAndVertically+0x28>
jmp    1244 <largestProductHorizontallyAndVertically+0x144>
mov    -0x24(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x24(%rbp)
jmp    1117 <largestProductHorizontallyAndVertically+0x17>
mov    -0x20(%rbp),%rax
pop    %rbp
ret

x86 assembly (clang, -O2):
<largestProductHorizontallyAndVertically>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
lea    0xc(%rdi),%r10
lea    0x50(%rdi),%r8
mov    $0x1,%eax
xor    %r9d,%r9d
nopw   0x0(%rax,%rax,1)
mov    (%rdi,%r9,4),%ecx
lea    (%r9,%r9,4),%rdx
shl    $0x4,%rdx
mov    (%rdi,%rdx,1),%r11d
mov    %r8,%rsi
xor    %edx,%edx
cs nopw 0x0(%rax,%rax,1)
nop
movslq %ecx,%r12
movslq %r11d,%r14
movslq -0x8(%r10,%rdx,4),%r11
movslq -0x4(%r10,%rdx,4),%r15
movslq (%r10,%rdx,4),%rbx
lea    0x1(%rdx),%r13
movslq (%rsi),%rcx
imul   %rcx,%r12
imul   %r11,%r14
movslq 0x50(%rsi),%rdx
movslq 0xa0(%rsi),%rbp
add    $0x50,%rsi
imul   %rdx,%rbp
imul   %r12,%rbp
imul   %r15,%rbx
imul   %r14,%rbx
cmp    %rax,%rbx
cmova  %rbx,%rax
cmp    %rbp,%rax
cmovbe %rbp,%rax
mov    %r13,%rdx
cmp    $0x10,%r13
jne    1140 <largestProductHorizontallyAndVertically+0x40>
add    $0x1,%r9
add    $0x50,%r10
add    $0x4,%r8
cmp    $0x10,%r9
jne    1120 <largestProductHorizontallyAndVertically+0x20>
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define i64 @largestProductHorizontallyAndVertically([20 x i32]* %0) {
%2 = alloca [20 x i32]*
%3 = alloca i64
%4 = alloca i64
%5 = alloca i64
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
store [20 x i32]* %0, [20 x i32]** %2
store i64 1, i64* %5
store i32 0, i32* %6
br label %9
9: ; preds = %86, %1
%10 = load i32, i32* %6
%11 = icmp slt i32 %10, 16
br i1 %11, label %12, label %89
12: ; preds = %9
store i32 0, i32* %7
br label %13
13: ; preds = %82, %12
%14 = load i32, i32* %7
%15 = icmp slt i32 %14, 16
br i1 %15, label %16, label %85
16: ; preds = %13
store i64 1, i64* %4
store i64 1, i64* %3
%17 = load i32, i32* %7
store i32 %17, i32* %8
br label %18
18: ; preds = %53, %16
%19 = load i32, i32* %8
%20 = load i32, i32* %7
%21 = add nsw i32 %20, 4
%22 = icmp slt i32 %19, %21
br i1 %22, label %23, label %56
23: ; preds = %18
%24 = load i32, i32* %8
%25 = icmp slt i32 %24, 0
br i1 %25, label %29, label %26
26: ; preds = %23
%27 = load i32, i32* %8
%28 = icmp sge i32 %27, 20
br i1 %28, label %29, label %30
29: ; preds = %26, %23
br label %53
30: ; preds = %26
%31 = load [20 x i32]*, [20 x i32]** %2
%32 = load i32, i32* %6
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds [20 x i32], [20 x i32]* %31, i64 %33
%35 = load i32, i32* %8
%36 = sext i32 %35 to i64
%37 = getelementptr inbounds [20 x i32], [20 x i32]* %34, i64 0, i64 %36
%38 = load i32, i32* %37
%39 = sext i32 %38 to i64
%40 = load i64, i64* %3
%41 = mul i64 %40, %39
store i64 %41, i64* %3
%42 = load [20 x i32]*, [20 x i32]** %2
%43 = load i32, i32* %8
%44 = sext i32 %43 to i64
%45 = getelementptr inbounds [20 x i32], [20 x i32]* %42, i64 %44
%46 = load i32, i32* %6
%47 = sext i32 %46 to i64
%48 = getelementptr inbounds [20 x i32], [20 x i32]* %45, i64 0, i64 %47
%49 = load i32, i32* %48
%50 = sext i32 %49 to i64
%51 = load i64, i64* %4
%52 = mul i64 %51, %50
store i64 %52, i64* %4
br label %53
53: ; preds = %30, %29
%54 = load i32, i32* %8
%55 = add nsw i32 %54, 1
store i32 %55, i32* %8
br label %18
56: ; preds = %18
%57 = load i64, i64* %3
%58 = load i64, i64* %5
%59 = icmp ugt i64 %57, %58
br i1 %59, label %60, label %62
60: ; preds = %56
%61 = load i64, i64* %3
br label %64
62: ; preds = %56
%63 = load i64, i64* %5
br label %64
64: ; preds = %62, %60
%65 = phi i64 [ %61, %60 ], [ %63, %62 ]
%66 = load i64, i64* %4
%67 = icmp ugt i64 %65, %66
br i1 %67, label %68, label %78
68: ; preds = %64
%69 = load i64, i64* %3
%70 = load i64, i64* %5
%71 = icmp ugt i64 %69, %70
br i1 %71, label %72, label %74
72: ; preds = %68
%73 = load i64, i64* %3
br label %76
74: ; preds = %68
%75 = load i64, i64* %5
br label %76
76: ; preds = %74, %72
%77 = phi i64 [ %73, %72 ], [ %75, %74 ]
br label %80
78: ; preds = %64
%79 = load i64, i64* %4
br label %80
80: ; preds = %78, %76
%81 = phi i64 [ %77, %76 ], [ %79, %78 ]
store i64 %81, i64* %5
br label %82
82: ; preds = %80
%83 = load i32, i32* %7
%84 = add nsw i32 %83, 1
store i32 %84, i32* %7
br label %13
85: ; preds = %13
br label %86
86: ; preds = %85
%87 = load i32, i32* %6
%88 = add nsw i32 %87, 1
store i32 %88, i32* %6
br label %9
89: ; preds = %9
%90 = load i64, i64* %5
ret i64 %90
}

LLVM IR (-O2):
define i64 @largestProductHorizontallyAndVertically([20 x i32]* nocapture %0) {
br label %2
2: ; preds = %1, %49
%3 = phi i64 [ 0, %1 ], [ %50, %49 ]
%4 = phi i64 [ 1, %1 ], [ %47, %49 ]
%5 = getelementptr inbounds [20 x i32], [20 x i32]* %0, i64 0, i64 %3
%6 = load i32, i32* %5
%7 = getelementptr inbounds [20 x i32], [20 x i32]* %0, i64 %3, i64 0
%8 = load i32, i32* %7
br label %10
9: ; preds = %49
ret i64 %47
10: ; preds = %2, %10
%11 = phi i32 [ %8, %2 ], [ %23, %10 ]
%12 = phi i32 [ %6, %2 ], [ %19, %10 ]
%13 = phi i64 [ 0, %2 ], [ %17, %10 ]
%14 = phi i64 [ %4, %2 ], [ %47, %10 ]
%15 = sext i32 %12 to i64
%16 = sext i32 %11 to i64
%17 = add nuw nsw i64 %13, 1
%18 = getelementptr inbounds [20 x i32], [20 x i32]* %0, i64 %17, i64 %3
%19 = load i32, i32* %18
%20 = sext i32 %19 to i64
%21 = mul nsw i64 %15, %20
%22 = getelementptr inbounds [20 x i32], [20 x i32]* %0, i64 %3, i64 %17
%23 = load i32, i32* %22
%24 = sext i32 %23 to i64
%25 = mul nsw i64 %16, %24
%26 = add nuw nsw i64 %13, 2
%27 = getelementptr inbounds [20 x i32], [20 x i32]* %0, i64 %26, i64 %3
%28 = load i32, i32* %27
%29 = sext i32 %28 to i64
%30 = mul i64 %21, %29
%31 = getelementptr inbounds [20 x i32], [20 x i32]* %0, i64 %3, i64 %26
%32 = load i32, i32* %31
%33 = sext i32 %32 to i64
%34 = mul i64 %25, %33
%35 = add nuw nsw i64 %13, 3
%36 = getelementptr inbounds [20 x i32], [20 x i32]* %0, i64 %35, i64 %3
%37 = load i32, i32* %36
%38 = sext i32 %37 to i64
%39 = mul i64 %30, %38
%40 = getelementptr inbounds [20 x i32], [20 x i32]* %0, i64 %3, i64 %35
%41 = load i32, i32* %40
%42 = sext i32 %41 to i64
%43 = mul i64 %34, %42
%44 = icmp ugt i64 %43, %14
%45 = select i1 %44, i64 %43, i64 %14
%46 = icmp ugt i64 %45, %39
%47 = select i1 %46, i64 %45, i64 %39
%48 = icmp eq i64 %17, 16
br i1 %48, label %49, label %10
49: ; preds = %10
%50 = add nuw nsw i64 %3, 1
%51 = icmp eq i64 %50, 16
br i1 %51, label %9, label %2
}