int _ssub2(int src1, int src2) {
  signed short s1[2], s2[2];
  signed int r[2], maxv, minv;
  maxv = (1L << (16 - 1)) - 1;
  minv = (-1L << (16 - 1));
  *((int *)s1) = src1;
  *((int *)s2) = src2;
  r[0] = (int)s1[0] - (int)s2[0];
  r[1] = (int)s1[1] - (int)s2[1];
  if (r[0] > maxv) {
    r[0] = maxv;
  } else if (r[0] < minv) {
    r[0] = minv;
  }
  if (r[1] > maxv) {
    r[1] = maxv;
  } else if (r[1] < minv) {
    r[1] = minv;
  }
  return ((r[1] & 0xffff) << 16) | (r[0] & 0xffff);
}


x86 assembly (clang, -O0):
<_ssub2>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
movl   $0x7fff,-0x1c(%rbp)
movl   $0xffff8000,-0x20(%rbp)
mov    -0x4(%rbp),%eax
mov    %eax,-0xc(%rbp)
mov    -0x8(%rbp),%eax
mov    %eax,-0x10(%rbp)
movswl -0xc(%rbp),%eax
movswl -0x10(%rbp),%ecx
sub    %ecx,%eax
mov    %eax,-0x18(%rbp)
movswl -0xa(%rbp),%eax
movswl -0xe(%rbp),%ecx
sub    %ecx,%eax
mov    %eax,-0x14(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jle    1155 <_ssub2+0x55>
mov    -0x1c(%rbp),%eax
mov    %eax,-0x18(%rbp)
jmp    116c <_ssub2+0x6c>
mov    -0x18(%rbp),%eax
cmp    -0x20(%rbp),%eax
jge    1167 <_ssub2+0x67>
mov    -0x20(%rbp),%eax
mov    %eax,-0x18(%rbp)
jmp    116c <_ssub2+0x6c>
mov    -0x14(%rbp),%eax
cmp    -0x1c(%rbp),%eax
jle    1183 <_ssub2+0x83>
mov    -0x1c(%rbp),%eax
mov    %eax,-0x14(%rbp)
jmp    119a <_ssub2+0x9a>
mov    -0x14(%rbp),%eax
cmp    -0x20(%rbp),%eax
jge    1195 <_ssub2+0x95>
mov    -0x20(%rbp),%eax
mov    %eax,-0x14(%rbp)
jmp    119a <_ssub2+0x9a>
mov    -0x14(%rbp),%eax
and    $0xffff,%eax
shl    $0x10,%eax
mov    -0x18(%rbp),%ecx
and    $0xffff,%ecx
or     %ecx,%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<_ssub2>:
mov    %edi,%eax
shr    $0x10,%eax
mov    %esi,%ecx
shr    $0x10,%ecx
xor    %edx,%edx
cmp    %cx,%ax
setns  %dl
add    $0x7fff,%edx
sub    %cx,%ax
cmovo  %edx,%eax
xor    %ecx,%ecx
cmp    %si,%di
setns  %cl
add    $0x7fff,%ecx
sub    %si,%di
cmovo  %ecx,%edi
movzwl %di,%ecx
shl    $0x10,%eax
or     %ecx,%eax
ret

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

LLVM IR (-O2):
define i32 @_ssub2(i32 %0, i32 %1) {
%3 = lshr i32 %0, 16
%4 = lshr i32 %1, 16
%5 = trunc i32 %0 to i16
%6 = trunc i32 %1 to i16
%7 = tail call i16 @llvm.ssub.sat.i16(i16 %5, i16 %6)
%8 = zext i16 %7 to i32
%9 = trunc i32 %3 to i16
%10 = trunc i32 %4 to i16
%11 = tail call i16 @llvm.ssub.sat.i16(i16 %9, i16 %10)
%12 = sext i16 %11 to i32
%13 = shl nsw i32 %12, 16
%14 = or i32 %13, %8
ret i32 %14
}