void separation_point_shear_stress(double *x_loc, double dx, double dy, int il,
                                   int imax, double **U, double **V) {
  int i;
  double dv_dx, du_dy, stress, stress_ahead;
  du_dy = (U[imax][2] - U[imax][0]) / (2 * dy);
  dv_dx = (V[imax + 1][1] - V[imax - 1][1]) / (2 * dx);
  stress_ahead = du_dy + dv_dx;
  for (i = imax - 1; i > 1; i--) {
    du_dy = (U[i][2] - U[i][0]) / (2 * dy);
    dv_dx = (V[i + 1][1] - V[i - 1][1]) / (2 * dx);
    stress = du_dy + dv_dx;
    if (stress_ahead > 0 && stress < 0) {
      *x_loc = (il + i) * dx;
      break;
    }
    stress_ahead = stress;
  }
}


x86 assembly (clang, -O0):
<separation_point_shear_stress>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
movsd  %xmm0,-0x10(%rbp)
movsd  %xmm1,-0x18(%rbp)
mov    %esi,-0x1c(%rbp)
mov    %edx,-0x20(%rbp)
mov    %rcx,-0x28(%rbp)
mov    %r8,-0x30(%rbp)
mov    -0x28(%rbp),%rax
movslq -0x20(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movsd  0x10(%rax),%xmm0
mov    -0x28(%rbp),%rax
movslq -0x20(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
subsd  (%rax),%xmm0
movsd  0xeb7(%rip),%xmm1
mulsd  -0x18(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x30(%rbp),%rax
mov    -0x20(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movsd  0x8(%rax),%xmm0
mov    -0x30(%rbp),%rax
mov    -0x20(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
subsd  0x8(%rax),%xmm0
movsd  0xe75(%rip),%xmm1
mulsd  -0x10(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x48(%rbp),%xmm0
addsd  -0x40(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x20(%rbp),%eax
sub    $0x1,%eax
mov    %eax,-0x34(%rbp)
cmpl   $0x1,-0x34(%rbp)
jle    1297 <separation_point_shear_stress+0x197>
mov    -0x28(%rbp),%rax
movslq -0x34(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movsd  0x10(%rax),%xmm0
mov    -0x28(%rbp),%rax
movslq -0x34(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
subsd  (%rax),%xmm0
movsd  0xe1c(%rip),%xmm1
mulsd  -0x18(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x30(%rbp),%rax
mov    -0x34(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movsd  0x8(%rax),%xmm0
mov    -0x30(%rbp),%rax
mov    -0x34(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
subsd  0x8(%rax),%xmm0
movsd  0xdda(%rip),%xmm1
mulsd  -0x10(%rbp),%xmm1
divsd  %xmm1,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x48(%rbp),%xmm0
addsd  -0x40(%rbp),%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x58(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    127f <separation_point_shear_stress+0x17f>
xorps  %xmm0,%xmm0
ucomisd -0x50(%rbp),%xmm0
jbe    127f <separation_point_shear_stress+0x17f>
mov    -0x1c(%rbp),%eax
add    -0x34(%rbp),%eax
cvtsi2sd %eax,%xmm0
mulsd  -0x10(%rbp),%xmm0
mov    -0x8(%rbp),%rax
movsd  %xmm0,(%rax)
jmp    1297 <separation_point_shear_stress+0x197>
movsd  -0x50(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
mov    -0x34(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x34(%rbp)
jmp    11b1 <separation_point_shear_stress+0xb1>
pop    %rbp
ret

x86 assembly (clang, -O2):
<separation_point_shear_stress>:
movslq %edx,%r11
mov    (%rcx,%r11,8),%rdx
unpcklpd %xmm0,%xmm1
addpd  %xmm1,%xmm1
mov    -0x8(%r8,%r11,8),%r9
mov    0x8(%r8,%r11,8),%r10
movsd  (%rdx),%xmm2
movsd  0x10(%rdx),%xmm3
movhpd 0x8(%r10),%xmm3
movhpd 0x8(%r9),%xmm2
lea    -0x1(%r11),%r9d
subpd  %xmm2,%xmm3
divpd  %xmm1,%xmm3
movapd %xmm3,%xmm2
unpckhpd %xmm3,%xmm2
addsd  %xmm3,%xmm2
add    %r11d,%esi
add    $0xfffffffe,%r11d
xorpd  %xmm3,%xmm3
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
cmp    $0x2,%r9d
jl     11c9 <separation_point_shear_stress+0xc9>
mov    (%rcx,%r9,8),%rax
mov    0x8(%r8,%r9,8),%r10
add    $0xffffffffffffffff,%r9
mov    (%r8,%r11,8),%rdx
movsd  (%rax),%xmm4
movsd  0x10(%rax),%xmm5
movhpd 0x8(%r10),%xmm5
movhpd 0x8(%rdx),%xmm4
subpd  %xmm4,%xmm5
divpd  %xmm1,%xmm5
movapd %xmm5,%xmm4
unpckhpd %xmm5,%xmm4
addsd  %xmm5,%xmm4
add    $0xffffffff,%esi
add    $0xffffffffffffffff,%r11
ucomisd %xmm3,%xmm2
movapd %xmm4,%xmm2
jbe    1160 <separation_point_shear_stress+0x60>
ucomisd %xmm4,%xmm3
movapd %xmm4,%xmm2
jbe    1160 <separation_point_shear_stress+0x60>
xorps  %xmm1,%xmm1
cvtsi2sd %esi,%xmm1
mulsd  %xmm0,%xmm1
movsd  %xmm1,(%rdi)
ret

LLVM IR (-O0):
define void @separation_point_shear_stress(double* %0, double %1, double %2, i32 %3, i32 %4, double** %5, double** %6) {
%8 = alloca double*
%9 = alloca double
%10 = alloca double
%11 = alloca i32
%12 = alloca i32
%13 = alloca double**
%14 = alloca double**
%15 = alloca i32
%16 = alloca double
%17 = alloca double
%18 = alloca double
%19 = alloca double
store double* %0, double** %8
store double %1, double* %9
store double %2, double* %10
store i32 %3, i32* %11
store i32 %4, i32* %12
store double** %5, double*** %13
store double** %6, double*** %14
%20 = load double**, double*** %13
%21 = load i32, i32* %12
%22 = sext i32 %21 to i64
%23 = getelementptr inbounds double*, double** %20, i64 %22
%24 = load double*, double** %23
%25 = getelementptr inbounds double, double* %24, i64 2
%26 = load double, double* %25
%27 = load double**, double*** %13
%28 = load i32, i32* %12
%29 = sext i32 %28 to i64
%30 = getelementptr inbounds double*, double** %27, i64 %29
%31 = load double*, double** %30
%32 = getelementptr inbounds double, double* %31, i64 0
%33 = load double, double* %32
%34 = fsub double %26, %33
%35 = load double, double* %10
%36 = fmul double 2.000000e+00, %35
%37 = fdiv double %34, %36
store double %37, double* %17
%38 = load double**, double*** %14
%39 = load i32, i32* %12
%40 = add nsw i32 %39, 1
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds double*, double** %38, i64 %41
%43 = load double*, double** %42
%44 = getelementptr inbounds double, double* %43, i64 1
%45 = load double, double* %44
%46 = load double**, double*** %14
%47 = load i32, i32* %12
%48 = sub nsw i32 %47, 1
%49 = sext i32 %48 to i64
%50 = getelementptr inbounds double*, double** %46, i64 %49
%51 = load double*, double** %50
%52 = getelementptr inbounds double, double* %51, i64 1
%53 = load double, double* %52
%54 = fsub double %45, %53
%55 = load double, double* %9
%56 = fmul double 2.000000e+00, %55
%57 = fdiv double %54, %56
store double %57, double* %16
%58 = load double, double* %17
%59 = load double, double* %16
%60 = fadd double %58, %59
store double %60, double* %19
%61 = load i32, i32* %12
%62 = sub nsw i32 %61, 1
store i32 %62, i32* %15
br label %63
63: ; preds = %123, %7
%64 = load i32, i32* %15
%65 = icmp sgt i32 %64, 1
br i1 %65, label %66, label %126
66: ; preds = %63
%67 = load double**, double*** %13
%68 = load i32, i32* %15
%69 = sext i32 %68 to i64
%70 = getelementptr inbounds double*, double** %67, i64 %69
%71 = load double*, double** %70
%72 = getelementptr inbounds double, double* %71, i64 2
%73 = load double, double* %72
%74 = load double**, double*** %13
%75 = load i32, i32* %15
%76 = sext i32 %75 to i64
%77 = getelementptr inbounds double*, double** %74, i64 %76
%78 = load double*, double** %77
%79 = getelementptr inbounds double, double* %78, i64 0
%80 = load double, double* %79
%81 = fsub double %73, %80
%82 = load double, double* %10
%83 = fmul double 2.000000e+00, %82
%84 = fdiv double %81, %83
store double %84, double* %17
%85 = load double**, double*** %14
%86 = load i32, i32* %15
%87 = add nsw i32 %86, 1
%88 = sext i32 %87 to i64
%89 = getelementptr inbounds double*, double** %85, i64 %88
%90 = load double*, double** %89
%91 = getelementptr inbounds double, double* %90, i64 1
%92 = load double, double* %91
%93 = load double**, double*** %14
%94 = load i32, i32* %15
%95 = sub nsw i32 %94, 1
%96 = sext i32 %95 to i64
%97 = getelementptr inbounds double*, double** %93, i64 %96
%98 = load double*, double** %97
%99 = getelementptr inbounds double, double* %98, i64 1
%100 = load double, double* %99
%101 = fsub double %92, %100
%102 = load double, double* %9
%103 = fmul double 2.000000e+00, %102
%104 = fdiv double %101, %103
store double %104, double* %16
%105 = load double, double* %17
%106 = load double, double* %16
%107 = fadd double %105, %106
store double %107, double* %18
%108 = load double, double* %19
%109 = fcmp ogt double %108, 0.000000e+00
br i1 %109, label %110, label %121
110: ; preds = %66
%111 = load double, double* %18
%112 = fcmp olt double %111, 0.000000e+00
br i1 %112, label %113, label %121
113: ; preds = %110
%114 = load i32, i32* %11
%115 = load i32, i32* %15
%116 = add nsw i32 %114, %115
%117 = sitofp i32 %116 to double
%118 = load double, double* %9
%119 = fmul double %117, %118
%120 = load double*, double** %8
store double %119, double* %120
br label %126
121: ; preds = %110, %66
%122 = load double, double* %18
store double %122, double* %19
br label %123
123: ; preds = %121
%124 = load i32, i32* %15
%125 = add nsw i32 %124, -1
store i32 %125, i32* %15
br label %63
126: ; preds = %113, %63
ret void
}

LLVM IR (-O2):
define void @separation_point_shear_stress(double* nocapture writeonly %0, double %1, double %2, i32 %3, i32 %4, double** nocapture %5, double** nocapture %6) {
%8 = sext i32 %4 to i64
%9 = getelementptr inbounds double*, double** %5, i64 %8
%10 = load double*, double** %9
%11 = getelementptr inbounds double, double* %10, i64 2
%12 = load double, double* %11
%13 = load double, double* %10
%14 = insertelement <2 x double> poison, double %2, i64 0
%15 = insertelement <2 x double> %14, double %1, i64 1
%16 = fmul <2 x double> %15, <double 2.000000e+00, double 2.000000e+00>
%17 = add nsw i32 %4, 1
%18 = sext i32 %17 to i64
%19 = getelementptr inbounds double*, double** %6, i64 %18
%20 = load double*, double** %19
%21 = getelementptr inbounds double, double* %20, i64 1
%22 = load double, double* %21
%23 = add nsw i32 %4, -1
%24 = sext i32 %23 to i64
%25 = getelementptr inbounds double*, double** %6, i64 %24
%26 = load double*, double** %25
%27 = getelementptr inbounds double, double* %26, i64 1
%28 = load double, double* %27
%29 = insertelement <2 x double> poison, double %12, i64 0
%30 = insertelement <2 x double> %29, double %22, i64 1
%31 = insertelement <2 x double> poison, double %13, i64 0
%32 = insertelement <2 x double> %31, double %28, i64 1
%33 = fsub <2 x double> %30, %32
%34 = fdiv <2 x double> %33, %16
%35 = shufflevector <2 x double> %34, <2 x double> poison, <2 x i32> <i32 1, i32 undef>
%36 = fadd <2 x double> %34, %35
%37 = extractelement <2 x double> %36, i64 0
%38 = zext i32 %23 to i64
br label %39
39: ; preds = %44, %7
%40 = phi i64 [ %55, %44 ], [ %38, %7 ]
%41 = phi double [ %69, %44 ], [ %37, %7 ]
%42 = trunc i64 %40 to i32
%43 = icmp sgt i32 %42, 1
br i1 %43, label %44, label %78
44: ; preds = %39
%45 = getelementptr inbounds double*, double** %5, i64 %40
%46 = load double*, double** %45
%47 = getelementptr inbounds double, double* %46, i64 2
%48 = load double, double* %47
%49 = load double, double* %46
%50 = add nuw nsw i64 %40, 1
%51 = getelementptr inbounds double*, double** %6, i64 %50
%52 = load double*, double** %51
%53 = getelementptr inbounds double, double* %52, i64 1
%54 = load double, double* %53
%55 = add nsw i64 %40, -1
%56 = and i64 %55, 4294967295
%57 = getelementptr inbounds double*, double** %6, i64 %56
%58 = load double*, double** %57
%59 = getelementptr inbounds double, double* %58, i64 1
%60 = load double, double* %59
%61 = insertelement <2 x double> poison, double %48, i64 0
%62 = insertelement <2 x double> %61, double %54, i64 1
%63 = insertelement <2 x double> poison, double %49, i64 0
%64 = insertelement <2 x double> %63, double %60, i64 1
%65 = fsub <2 x double> %62, %64
%66 = fdiv <2 x double> %65, %16
%67 = shufflevector <2 x double> %66, <2 x double> poison, <2 x i32> <i32 1, i32 undef>
%68 = fadd <2 x double> %66, %67
%69 = extractelement <2 x double> %68, i64 0
%70 = fcmp ogt double %41, 0.000000e+00
%71 = fcmp olt double %69, 0.000000e+00
%72 = select i1 %70, i1 %71, i1 false
br i1 %72, label %73, label %39
73: ; preds = %44
%74 = trunc i64 %40 to i32
%75 = add nsw i32 %74, %3
%76 = sitofp i32 %75 to double
%77 = fmul double %76, %1
store double %77, double* %0
br label %78
78: ; preds = %39, %73
ret void
}