double polygon_area(int p[][2], int n) {
  int area = 0;
  int i;
  for (i = 1; i + 1 < n; i++) {
    int x1 = p[i][0] - p[0][0];
    int y1 = p[i][1] - p[0][1];
    int x2 = p[i + 1][0] - p[0][0];
    int y2 = p[i + 1][1] - p[0][1];
    int cross = x1 * y2 - x2 * y1;
    area += cross;
  }
  return area / 2.0;
}


x86 assembly (clang, -O0):
<polygon_area>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
movl   $0x0,-0x10(%rbp)
movl   $0x1,-0x14(%rbp)
mov    -0x14(%rbp),%eax
add    $0x1,%eax
cmp    -0xc(%rbp),%eax
jge    11b0 <polygon_area+0xb0>
mov    -0x8(%rbp),%rax
movslq -0x14(%rbp),%rcx
mov    (%rax,%rcx,8),%eax
mov    -0x8(%rbp),%rcx
sub    (%rcx),%eax
mov    %eax,-0x18(%rbp)
mov    -0x8(%rbp),%rax
movslq -0x14(%rbp),%rcx
mov    0x4(%rax,%rcx,8),%eax
mov    -0x8(%rbp),%rcx
sub    0x4(%rcx),%eax
mov    %eax,-0x1c(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%eax
mov    -0x8(%rbp),%rcx
sub    (%rcx),%eax
mov    %eax,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x14(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    0x4(%rax,%rcx,8),%eax
mov    -0x8(%rbp),%rcx
sub    0x4(%rcx),%eax
mov    %eax,-0x24(%rbp)
mov    -0x18(%rbp),%eax
imul   -0x24(%rbp),%eax
mov    -0x20(%rbp),%ecx
imul   -0x1c(%rbp),%ecx
sub    %ecx,%eax
mov    %eax,-0x28(%rbp)
mov    -0x28(%rbp),%eax
add    -0x10(%rbp),%eax
mov    %eax,-0x10(%rbp)
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
jmp    1119 <polygon_area+0x19>
cvtsi2sdl -0x10(%rbp),%xmm0
movsd  0xe43(%rip),%xmm1
divsd  %xmm1,%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<polygon_area>:
pxor   %xmm0,%xmm0
cmp    $0x3,%esi
jl     1328 <polygon_area+0x228>
push   %rbp
push   %r15
push   %r14
push   %rbx
mov    (%rdi),%r14d
mov    0x4(%rdi),%r15d
add    $0xffffffff,%esi
lea    -0x1(%rsi),%r10
cmp    $0x8,%r10
jae    113a <polygon_area+0x3a>
xor    %edx,%edx
mov    $0x2,%r8d
mov    $0x1,%r9d
jmp    12c1 <polygon_area+0x1c1>
mov    %r10,%r11
and    $0xfffffffffffffff8,%r11
lea    0x1(%r11),%r9
lea    0x2(%r11),%r8
movd   %r14d,%xmm0
pshufd $0x0,%xmm0,%xmm8
movd   %r15d,%xmm0
pshufd $0x0,%xmm0,%xmm9
pxor   %xmm1,%xmm1
xor    %edx,%edx
pxor   %xmm3,%xmm3
nopl   0x0(%rax)
movups 0x38(%rdi,%rdx,8),%xmm10
movups 0x28(%rdi,%rdx,8),%xmm5
movups 0x8(%rdi,%rdx,8),%xmm4
movups 0x10(%rdi,%rdx,8),%xmm0
movups 0x18(%rdi,%rdx,8),%xmm2
movups 0x20(%rdi,%rdx,8),%xmm12
movaps %xmm4,%xmm7
shufps $0x88,%xmm2,%xmm7
movaps %xmm5,%xmm6
shufps $0x88,%xmm10,%xmm6
shufps $0xdd,%xmm2,%xmm4
shufps $0xdd,%xmm10,%xmm5
psubd  %xmm8,%xmm7
psubd  %xmm8,%xmm6
movdqa %xmm9,%xmm11
psubd  %xmm4,%xmm11
movdqa %xmm9,%xmm10
psubd  %xmm5,%xmm10
movups 0x40(%rdi,%rdx,8),%xmm13
movups 0x30(%rdi,%rdx,8),%xmm5
movaps %xmm0,%xmm2
shufps $0x88,%xmm12,%xmm2
movaps %xmm5,%xmm4
shufps $0x88,%xmm13,%xmm4
shufps $0xdd,%xmm12,%xmm0
shufps $0xdd,%xmm13,%xmm5
psubd  %xmm8,%xmm2
psubd  %xmm8,%xmm4
psubd  %xmm9,%xmm0
psubd  %xmm9,%xmm5
pshufd $0xf5,%xmm0,%xmm12
pmuludq %xmm7,%xmm0
pshufd $0xe8,%xmm0,%xmm0
pshufd $0xf5,%xmm7,%xmm7
pmuludq %xmm12,%xmm7
pshufd $0xe8,%xmm7,%xmm7
punpckldq %xmm7,%xmm0
pshufd $0xf5,%xmm5,%xmm7
pmuludq %xmm6,%xmm5
pshufd $0xe8,%xmm5,%xmm5
pshufd $0xf5,%xmm6,%xmm6
pmuludq %xmm7,%xmm6
pshufd $0xe8,%xmm6,%xmm6
punpckldq %xmm6,%xmm5
pshufd $0xf5,%xmm2,%xmm6
pmuludq %xmm11,%xmm2
pshufd $0xe8,%xmm2,%xmm2
pshufd $0xf5,%xmm11,%xmm7
pmuludq %xmm6,%xmm7
pshufd $0xe8,%xmm7,%xmm6
punpckldq %xmm6,%xmm2
paddd  %xmm2,%xmm1
paddd  %xmm0,%xmm1
pshufd $0xf5,%xmm4,%xmm0
pmuludq %xmm10,%xmm4
pshufd $0xe8,%xmm4,%xmm2
pshufd $0xf5,%xmm10,%xmm4
pmuludq %xmm0,%xmm4
pshufd $0xe8,%xmm4,%xmm0
punpckldq %xmm0,%xmm2
paddd  %xmm2,%xmm3
paddd  %xmm5,%xmm3
add    $0x8,%rdx
cmp    %rdx,%r11
jne    1170 <polygon_area+0x70>
paddd  %xmm1,%xmm3
pshufd $0xee,%xmm3,%xmm0
paddd  %xmm3,%xmm0
pshufd $0x55,%xmm0,%xmm1
paddd  %xmm0,%xmm1
movd   %xmm1,%edx
cmp    %r11,%r10
je     1313 <polygon_area+0x213>
lea    (%rdi,%r9,8),%r10
add    $0x4,%r10
sub    %r9,%rsi
lea    (%rdi,%r8,8),%r8
add    $0x4,%r8
xor    %ebx,%ebx
mov    %edx,%ebp
nopl   0x0(%rax,%rax,1)
mov    -0x4(%r10,%rbx,8),%ecx
sub    %r14d,%ecx
mov    %r15d,%eax
sub    (%r10,%rbx,8),%eax
mov    -0x4(%r8,%rbx,8),%edi
mov    (%r8,%rbx,8),%edx
sub    %r14d,%edi
imul   %eax,%edi
add    %ebp,%edi
sub    %r15d,%edx
imul   %ecx,%edx
add    %edi,%edx
add    $0x1,%rbx
mov    %edx,%ebp
cmp    %rbx,%rsi
jne    12e0 <polygon_area+0x1e0>
xorps  %xmm0,%xmm0
cvtsi2sd %edx,%xmm0
mulsd  0xcde(%rip),%xmm0
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

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

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