float truncf(float x) {
  union {
    float f;
    int i;
    struct {
      int i1;
    };
  } u = {x};
  int exp = ((u.i1 >> 23) & 0xFF) - 127;
  if (exp >= 24)
    return x;
  if (exp < 0)
    return u.i &= 0x80000000, u.f;
  return u.i &= ~(0x000FFFFF >> exp), u.f;
}


x86 assembly (clang, -O0):
<truncf>:
push   %rbp
mov    %rsp,%rbp
movss  %xmm0,-0x8(%rbp)
movss  -0x8(%rbp),%xmm0
movss  %xmm0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
sar    $0x17,%eax
and    $0xff,%eax
sub    $0x7f,%eax
mov    %eax,-0x14(%rbp)
cmpl   $0x18,-0x14(%rbp)
jl     113d <truncf+0x3d>
movss  -0x8(%rbp),%xmm0
movss  %xmm0,-0x4(%rbp)
jmp    117e <truncf+0x7e>
cmpl   $0x0,-0x14(%rbp)
jge    1161 <truncf+0x61>
mov    -0x10(%rbp),%eax
and    $0x80000000,%eax
mov    %eax,-0x10(%rbp)
movss  -0x10(%rbp),%xmm0
movss  %xmm0,-0x4(%rbp)
jmp    117e <truncf+0x7e>
mov    -0x14(%rbp),%ecx
mov    $0xfffff,%eax
sar    %cl,%eax
xor    $0xffffffff,%eax
and    -0x10(%rbp),%eax
mov    %eax,-0x10(%rbp)
movss  -0x10(%rbp),%xmm0
movss  %xmm0,-0x4(%rbp)
movss  -0x4(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<truncf>:
movd   %xmm0,%eax
mov    %eax,%ecx
shr    $0x17,%ecx
movzbl %cl,%ecx
cmp    $0x96,%ecx
ja     1133 <truncf+0x33>
cmp    $0x7e,%ecx
ja     1123 <truncf+0x23>
and    $0x80000000,%eax
movd   %eax,%xmm0
ret
add    $0xffffff81,%ecx
mov    $0xfff00000,%edx
sar    %cl,%edx
and    %eax,%edx
movd   %edx,%xmm0
ret

LLVM IR (-O0):
%union.anon = type { float }
%struct.anon = type { i32 }
define float @truncf(float %0) {
%2 = alloca float
%3 = alloca float
%4 = alloca %union.anon
%5 = alloca i32
store float %0, float* %3
%6 = bitcast %union.anon* %4 to float*
%7 = load float, float* %3
store float %7, float* %6
%8 = bitcast %union.anon* %4 to %struct.anon*
%9 = getelementptr inbounds %struct.anon, %struct.anon* %8, i32 0, i32 0
%10 = load i32, i32* %9
%11 = ashr i32 %10, 23
%12 = and i32 %11, 255
%13 = sub nsw i32 %12, 127
store i32 %13, i32* %5
%14 = load i32, i32* %5
%15 = icmp sge i32 %14, 24
br i1 %15, label %16, label %18
16: ; preds = %1
%17 = load float, float* %3
store float %17, float* %2
br label %36
18: ; preds = %1
%19 = load i32, i32* %5
%20 = icmp slt i32 %19, 0
br i1 %20, label %21, label %27
21: ; preds = %18
%22 = bitcast %union.anon* %4 to i32*
%23 = load i32, i32* %22
%24 = and i32 %23, -2147483648
store i32 %24, i32* %22
%25 = bitcast %union.anon* %4 to float*
%26 = load float, float* %25
store float %26, float* %2
br label %36
27: ; preds = %18
%28 = load i32, i32* %5
%29 = ashr i32 1048575, %28
%30 = xor i32 %29, -1
%31 = bitcast %union.anon* %4 to i32*
%32 = load i32, i32* %31
%33 = and i32 %32, %30
store i32 %33, i32* %31
%34 = bitcast %union.anon* %4 to float*
%35 = load float, float* %34
store float %35, float* %2
br label %36
36: ; preds = %27, %21, %16
%37 = load float, float* %2
ret float %37
}

LLVM IR (-O2):
define float @truncf(float %0) {
%2 = bitcast float %0 to i32
%3 = lshr i32 %2, 23
%4 = and i32 %3, 255
%5 = add nsw i32 %4, -127
%6 = icmp ugt i32 %4, 150
br i1 %6, label %16, label %7
7: ; preds = %1
%8 = icmp ult i32 %4, 127
br i1 %8, label %9, label %12
9: ; preds = %7
%10 = and i32 %2, -2147483648
%11 = bitcast i32 %10 to float
br label %16
12: ; preds = %7
%13 = ashr i32 -1048576, %5
%14 = and i32 %13, %2
%15 = bitcast i32 %14 to float
br label %16
16: ; preds = %1, %12, %9
%17 = phi float [ %11, %9 ], [ %15, %12 ], [ %0, %1 ]
ret float %17
}