#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);
double sqrt(double);
double snrm(unsigned long n, double sx[], int itol) {
  unsigned long i, isamax;
  double ans;
  if (itol <= 3) {
    ans = 0.0;
    for (i = 1; i <= n; i++)
      ans += sx[i] * sx[i];
    return sqrt(ans);
  } else {
    isamax = 1;
    for (i = 1; i <= n; i++) {
      if (fabs(sx[i]) > fabs(sx[isamax]))
        isamax = i;
    }
    return fabs(sx[isamax]);
  }
}


x86 assembly (clang, -O0):
<snrm>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %edx,-0x1c(%rbp)
cmpl   $0x3,-0x1c(%rbp)
jg     119c <snrm+0x8c>
xorps  %xmm0,%xmm0
movsd  %xmm0,-0x38(%rbp)
movq   $0x1,-0x28(%rbp)
mov    -0x28(%rbp),%rax
cmp    -0x10(%rbp),%rax
ja     1188 <snrm+0x78>
mov    -0x18(%rbp),%rax
mov    -0x28(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
mov    -0x18(%rbp),%rax
mov    -0x28(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm2
movsd  -0x38(%rbp),%xmm1
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
movsd  %xmm0,-0x38(%rbp)
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    113d <snrm+0x2d>
movsd  -0x38(%rbp),%xmm0
call   1030 <sqrt@plt>
movsd  %xmm0,-0x8(%rbp)
jmp    122f <snrm+0x11f>
movq   $0x1,-0x30(%rbp)
movq   $0x1,-0x28(%rbp)
mov    -0x28(%rbp),%rax
cmp    -0x10(%rbp),%rax
ja     1212 <snrm+0x102>
mov    -0x18(%rbp),%rax
mov    -0x28(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movaps 0xe32(%rip),%xmm1
pand   %xmm1,%xmm0
mov    -0x18(%rbp),%rax
mov    -0x30(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm1
movaps 0xe1a(%rip),%xmm2
pand   %xmm2,%xmm1
ucomisd %xmm1,%xmm0
jbe    11fc <snrm+0xec>
mov    -0x28(%rbp),%rax
mov    %rax,-0x30(%rbp)
jmp    1201 <snrm+0xf1>
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    11ac <snrm+0x9c>
mov    -0x18(%rbp),%rax
mov    -0x30(%rbp),%rcx
movsd  (%rax,%rcx,8),%xmm0
movaps 0xdda(%rip),%xmm1
pand   %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<snrm>:
cmp    $0x4,%edx
jge    114c <snrm+0x3c>
xorpd  %xmm1,%xmm1
xorpd  %xmm0,%xmm0
test   %rdi,%rdi
je     1216 <snrm+0x106>
lea    -0x1(%rdi),%rcx
mov    %edi,%eax
and    $0x3,%eax
cmp    $0x3,%rcx
jae    11a5 <snrm+0x95>
mov    $0x1,%ecx
xorpd  %xmm0,%xmm0
test   %rax,%rax
jne    11fa <snrm+0xea>
jmp    1216 <snrm+0x106>
test   %rdi,%rdi
je     1191 <snrm+0x81>
cmp    $0x1,%rdi
jne    1226 <snrm+0x116>
mov    $0x1,%r9d
mov    $0x1,%ecx
test   $0x1,%dil
je     1197 <snrm+0x87>
movsd  (%rsi,%rcx,8),%xmm0
movapd 0xe87(%rip),%xmm1
andpd  %xmm1,%xmm0
movsd  (%rsi,%r9,8),%xmm2
andpd  %xmm1,%xmm2
ucomisd %xmm2,%xmm0
cmova  %rcx,%r9
jmp    1197 <snrm+0x87>
mov    $0x1,%r9d
movsd  (%rsi,%r9,8),%xmm0
andps  0xe5c(%rip),%xmm0
ret
and    $0xfffffffffffffffc,%rdi
xorpd  %xmm0,%xmm0
xor    %ecx,%ecx
nop
movsd  0x8(%rsi,%rcx,8),%xmm2
movsd  0x10(%rsi,%rcx,8),%xmm3
mulsd  %xmm2,%xmm2
addsd  %xmm0,%xmm2
mulsd  %xmm3,%xmm3
addsd  %xmm2,%xmm3
movsd  0x18(%rsi,%rcx,8),%xmm2
mulsd  %xmm2,%xmm2
addsd  %xmm3,%xmm2
movsd  0x20(%rsi,%rcx,8),%xmm0
mulsd  %xmm0,%xmm0
addsd  %xmm2,%xmm0
add    $0x4,%rcx
cmp    %rcx,%rdi
jne    11b0 <snrm+0xa0>
add    $0x1,%rcx
test   %rax,%rax
je     1216 <snrm+0x106>
lea    (%rsi,%rcx,8),%rcx
xor    %edx,%edx
movsd  (%rcx,%rdx,8),%xmm2
mulsd  %xmm2,%xmm2
addsd  %xmm2,%xmm0
add    $0x1,%rdx
cmp    %rdx,%rax
jne    1200 <snrm+0xf0>
ucomisd %xmm1,%xmm0
jb     1221 <snrm+0x111>
sqrtsd %xmm0,%xmm0
ret
jmp    1030 <sqrt@plt>
mov    %rdi,%r8
and    $0xfffffffffffffffe,%r8
mov    $0x1,%r9d
movapd 0xdc5(%rip),%xmm0
mov    $0x1,%ecx
jmp    125d <snrm+0x14d>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
add    $0x2,%rcx
cmp    %r8,%rdx
je     1166 <snrm+0x56>
movsd  (%rsi,%rcx,8),%xmm1
andpd  %xmm0,%xmm1
movsd  (%rsi,%r9,8),%xmm2
andpd  %xmm0,%xmm2
ucomisd %xmm2,%xmm1
mov    %rcx,%rax
ja     127c <snrm+0x16c>
mov    %r9,%rax
movsd  0x8(%rsi,%rcx,8),%xmm1
andpd  %xmm0,%xmm1
movsd  (%rsi,%rax,8),%xmm2
andpd  %xmm0,%xmm2
lea    0x1(%rcx),%rdx
ucomisd %xmm2,%xmm1
mov    %rdx,%r9
ja     1250 <snrm+0x140>
mov    %rax,%r9
jmp    1250 <snrm+0x140>

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

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