#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
double fabs(double const);
double sqrt(double);
scalar_t__ square(double const);
double Norm(const double *x, int n) {
  int i;
  double maxElem = fabs(x[0]);
  for (i = 1; i < n; i++) {
    if (fabs(x[i]) > maxElem)
      maxElem = fabs(x[i]);
  }
  if (maxElem == 0) {
    return 0;
  }
  double r = 0;
  for (i = 0; i < n; i++) {
    r += square(x[i] / maxElem);
  }
  r = maxElem * sqrt(r);
  return r;
}


x86 assembly (clang, -O0):
<Norm>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    -0x10(%rbp),%rax
movsd  (%rax),%xmm0
movaps 0xec2(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
movl   $0x1,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    11ad <Norm+0x8d>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movaps 0xe92(%rip),%xmm1
pand   %xmm1,%xmm0
ucomisd -0x20(%rbp),%xmm0
jbe    119a <Norm+0x7a>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movaps 0xe6f(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  %xmm0,-0x20(%rbp)
jmp    119f <Norm+0x7f>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    114e <Norm+0x2e>
movsd  -0x20(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    11d2 <Norm+0xb2>
jp     11d2 <Norm+0xb2>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1250 <Norm+0x130>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x28(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    1221 <Norm+0x101>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
divsd  -0x20(%rbp),%xmm0
call   1030 <square@plt>
cvtsi2sd %rax,%xmm0
addsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x28(%rbp)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    11e1 <Norm+0xc1>
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0x30(%rbp)
movsd  -0x28(%rbp),%xmm0
call   1040 <sqrt@plt>
movaps %xmm0,%xmm1
movsd  -0x30(%rbp),%xmm0
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x28(%rbp)
movsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<Norm>:
push   %rbp
push   %r14
push   %rbx
sub    $0x20,%rsp
mov    %esi,%ebp
mov    %rdi,%rbx
movsd  (%rdi),%xmm0
movapd 0xec7(%rip),%xmm1
andpd  %xmm0,%xmm1
cmp    $0x2,%esi
jl     115e <Norm+0x3e>
mov    %ebp,%ecx
lea    -0x1(%rcx),%rdx
add    $0xfffffffffffffffe,%rcx
mov    %edx,%eax
and    $0x3,%eax
cmp    $0x3,%rcx
jae    1167 <Norm+0x47>
mov    $0x1,%ecx
jmp    11c5 <Norm+0xa5>
movapd %xmm1,%xmm3
jmp    11fa <Norm+0xda>
and    $0xfffffffffffffffc,%rdx
xor    %ecx,%ecx
movapd 0xe8b(%rip),%xmm2
cs nopw 0x0(%rax,%rax,1)
nop
movsd  0x8(%rbx,%rcx,8),%xmm3
movsd  0x10(%rbx,%rcx,8),%xmm4
movsd  0x18(%rbx,%rcx,8),%xmm5
andpd  %xmm2,%xmm3
maxsd  %xmm1,%xmm3
movsd  0x20(%rbx,%rcx,8),%xmm1
andpd  %xmm2,%xmm4
maxsd  %xmm3,%xmm4
andpd  %xmm2,%xmm5
maxsd  %xmm4,%xmm5
andpd  %xmm2,%xmm1
maxsd  %xmm5,%xmm1
add    $0x4,%rcx
cmp    %rcx,%rdx
jne    1180 <Norm+0x60>
add    $0x1,%rcx
movapd %xmm1,%xmm3
test   %rax,%rax
je     11fa <Norm+0xda>
lea    (%rbx,%rcx,8),%rcx
xor    %edx,%edx
movapd 0xe24(%rip),%xmm2
nopl   0x0(%rax)
movsd  (%rcx,%rdx,8),%xmm3
andpd  %xmm2,%xmm3
maxsd  %xmm1,%xmm3
add    $0x1,%rdx
movapd %xmm3,%xmm1
cmp    %rdx,%rax
jne    11e0 <Norm+0xc0>
xorpd  %xmm1,%xmm1
ucomisd %xmm1,%xmm3
jne    120a <Norm+0xea>
jnp    12ad <Norm+0x18d>
xorpd  %xmm1,%xmm1
test   %ebp,%ebp
movapd %xmm3,(%rsp)
jle    1284 <Norm+0x164>
divsd  %xmm3,%xmm0
call   1030 <square@plt>
xorps  %xmm1,%xmm1
cvtsi2sd %rax,%xmm1
cmp    $0x1,%ebp
jne    1234 <Norm+0x114>
movapd (%rsp),%xmm3
jmp    1284 <Norm+0x164>
mov    %ebp,%r14d
mov    $0x1,%ebp
movapd (%rsp),%xmm3
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movsd  %xmm1,0x18(%rsp)
movsd  (%rbx,%rbp,8),%xmm0
divsd  %xmm3,%xmm0
call   1030 <square@plt>
movsd  0x18(%rsp),%xmm1
movapd (%rsp),%xmm3
xorps  %xmm0,%xmm0
cvtsi2sd %rax,%xmm0
addsd  %xmm0,%xmm1
add    $0x1,%rbp
cmp    %rbp,%r14
jne    1250 <Norm+0x130>
ucomisd 0xd84(%rip),%xmm1
jb     1297 <Norm+0x177>
xorps  %xmm0,%xmm0
sqrtsd %xmm1,%xmm0
jmp    12a5 <Norm+0x185>
movapd %xmm1,%xmm0
call   1040 <sqrt@plt>
movapd (%rsp),%xmm3
mulsd  %xmm0,%xmm3
movapd %xmm3,%xmm1
movapd %xmm1,%xmm0
add    $0x20,%rsp
pop    %rbx
pop    %r14
pop    %rbp
ret

LLVM IR (-O0):
define double @Norm(double* %0, i32 %1) {
%3 = alloca double
%4 = alloca double*
%5 = alloca i32
%6 = alloca i32
%7 = alloca double
%8 = alloca double
store double* %0, double** %4
store i32 %1, i32* %5
%9 = load double*, double** %4
%10 = getelementptr inbounds double, double* %9, i64 0
%11 = load double, double* %10
%12 = call double @llvm.fabs.f64(double %11)
store double %12, double* %7
store i32 1, i32* %6
br label %13
13: ; preds = %34, %2
%14 = load i32, i32* %6
%15 = load i32, i32* %5
%16 = icmp slt i32 %14, %15
br i1 %16, label %17, label %37
17: ; preds = %13
%18 = load double*, double** %4
%19 = load i32, i32* %6
%20 = sext i32 %19 to i64
%21 = getelementptr inbounds double, double* %18, i64 %20
%22 = load double, double* %21
%23 = call double @llvm.fabs.f64(double %22)
%24 = load double, double* %7
%25 = fcmp ogt double %23, %24
br i1 %25, label %26, label %33
26: ; preds = %17
%27 = load double*, double** %4
%28 = load i32, i32* %6
%29 = sext i32 %28 to i64
%30 = getelementptr inbounds double, double* %27, i64 %29
%31 = load double, double* %30
%32 = call double @llvm.fabs.f64(double %31)
store double %32, double* %7
br label %33
33: ; preds = %26, %17
br label %34
34: ; preds = %33
%35 = load i32, i32* %6
%36 = add nsw i32 %35, 1
store i32 %36, i32* %6
br label %13
37: ; preds = %13
%38 = load double, double* %7
%39 = fcmp oeq double %38, 0.000000e+00
br i1 %39, label %40, label %41
40: ; preds = %37
store double 0.000000e+00, double* %3
br label %67
41: ; preds = %37
store double 0.000000e+00, double* %8
store i32 0, i32* %6
br label %42
42: ; preds = %58, %41
%43 = load i32, i32* %6
%44 = load i32, i32* %5
%45 = icmp slt i32 %43, %44
br i1 %45, label %46, label %61
46: ; preds = %42
%47 = load double*, double** %4
%48 = load i32, i32* %6
%49 = sext i32 %48 to i64
%50 = getelementptr inbounds double, double* %47, i64 %49
%51 = load double, double* %50
%52 = load double, double* %7
%53 = fdiv double %51, %52
%54 = call i64 @square(double %53)
%55 = sitofp i64 %54 to double
%56 = load double, double* %8
%57 = fadd double %56, %55
store double %57, double* %8
br label %58
58: ; preds = %46
%59 = load i32, i32* %6
%60 = add nsw i32 %59, 1
store i32 %60, i32* %6
br label %42
61: ; preds = %42
%62 = load double, double* %7
%63 = load double, double* %8
%64 = call double @sqrt(double %63)
%65 = fmul double %62, %64
store double %65, double* %8
%66 = load double, double* %8
store double %66, double* %3
br label %67
67: ; preds = %61, %40
%68 = load double, double* %3
ret double %68
}

LLVM IR (-O2):
define double @Norm(double* nocapture %0, i32 %1) {
%3 = load double, double* %0
%4 = tail call double @llvm.fabs.f64(double %3)
%5 = icmp sgt i32 %1, 1
br i1 %5, label %6, label %61
6: ; preds = %2
%7 = zext i32 %1 to i64
%8 = add nsw i64 %7, -1
%9 = add nsw i64 %7, -2
%10 = and i64 %8, 3
%11 = icmp ult i64 %9, 3
br i1 %11, label %44, label %12
12: ; preds = %6
%13 = and i64 %8, -4
br label %14
14: ; preds = %14, %12
%15 = phi i64 [ 1, %12 ], [ %41, %14 ]
%16 = phi double [ %4, %12 ], [ %40, %14 ]
%17 = phi i64 [ 0, %12 ], [ %42, %14 ]
%18 = getelementptr inbounds double, double* %0, i64 %15
%19 = load double, double* %18
%20 = tail call double @llvm.fabs.f64(double %19)
%21 = fcmp ogt double %20, %16
%22 = select i1 %21, double %20, double %16
%23 = add nuw nsw i64 %15, 1
%24 = getelementptr inbounds double, double* %0, i64 %23
%25 = load double, double* %24
%26 = tail call double @llvm.fabs.f64(double %25)
%27 = fcmp ogt double %26, %22
%28 = select i1 %27, double %26, double %22
%29 = add nuw nsw i64 %15, 2
%30 = getelementptr inbounds double, double* %0, i64 %29
%31 = load double, double* %30
%32 = tail call double @llvm.fabs.f64(double %31)
%33 = fcmp ogt double %32, %28
%34 = select i1 %33, double %32, double %28
%35 = add nuw nsw i64 %15, 3
%36 = getelementptr inbounds double, double* %0, i64 %35
%37 = load double, double* %36
%38 = tail call double @llvm.fabs.f64(double %37)
%39 = fcmp ogt double %38, %34
%40 = select i1 %39, double %38, double %34
%41 = add nuw nsw i64 %15, 4
%42 = add i64 %17, 4
%43 = icmp eq i64 %42, %13
br i1 %43, label %44, label %14
44: ; preds = %14, %6
%45 = phi double [ undef, %6 ], [ %40, %14 ]
%46 = phi i64 [ 1, %6 ], [ %41, %14 ]
%47 = phi double [ %4, %6 ], [ %40, %14 ]
%48 = icmp eq i64 %10, 0
br i1 %48, label %61, label %49
49: ; preds = %44, %49
%50 = phi i64 [ %58, %49 ], [ %46, %44 ]
%51 = phi double [ %57, %49 ], [ %47, %44 ]
%52 = phi i64 [ %59, %49 ], [ 0, %44 ]
%53 = getelementptr inbounds double, double* %0, i64 %50
%54 = load double, double* %53
%55 = tail call double @llvm.fabs.f64(double %54)
%56 = fcmp ogt double %55, %51
%57 = select i1 %56, double %55, double %51
%58 = add nuw nsw i64 %50, 1
%59 = add i64 %52, 1
%60 = icmp eq i64 %59, %10
br i1 %60, label %61, label %49
61: ; preds = %44, %49, %2
%62 = phi double [ %4, %2 ], [ %45, %44 ], [ %57, %49 ]
%63 = fcmp oeq double %62, 0.000000e+00
br i1 %63, label %87, label %64
64: ; preds = %61
%65 = icmp sgt i32 %1, 0
br i1 %65, label %66, label %83
66: ; preds = %64
%67 = zext i32 %1 to i64
%68 = fdiv double %3, %62
%69 = tail call i64 @square(double %68)
%70 = sitofp i64 %69 to double
%71 = icmp eq i32 %1, 1
br i1 %71, label %83, label %72
72: ; preds = %66, %72
%73 = phi i64 [ %81, %72 ], [ 1, %66 ]
%74 = phi double [ %80, %72 ], [ %70, %66 ]
%75 = getelementptr inbounds double, double* %0, i64 %73
%76 = load double, double* %75
%77 = fdiv double %76, %62
%78 = tail call i64 @square(double %77)
%79 = sitofp i64 %78 to double
%80 = fadd double %74, %79
%81 = add nuw nsw i64 %73, 1
%82 = icmp eq i64 %81, %67
br i1 %82, label %83, label %72
83: ; preds = %72, %66, %64
%84 = phi double [ 0.000000e+00, %64 ], [ %70, %66 ], [ %80, %72 ]
%85 = tail call double @sqrt(double %84)
%86 = fmul double %62, %85
br label %87
87: ; preds = %61, %83
%88 = phi double [ %86, %83 ], [ 0.000000e+00, %61 ]
ret double %88
}