void test_add(int a, int b) {
  long out_flags;
  int out;
  __asm__ volatile("pushf\n"
                   "xorq %[flags], %[flags]\n"
                   "push %[flags]\n"
                   "popf\n"
                   "addl %[a], %[b]\n"
                   "pushf\n"
                   "pop %[flags]\n"
                   "popf\n"
                   : [flags] "=r"(out_flags), [b] "=r"(out)
                   : [a] "r"(a), "1"(b));
  printf("%08x:%08x:%08x:%x:%x\n", a, b, out, (out_flags & 0x0001) ? 1 : 0,
         (out_flags & 0x0800) ? 1 : 0);
}


x86 assembly (clang, -O0):
<test_add>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    -0x4(%rbp),%ecx
mov    -0x8(%rbp),%eax
pushf
xor    %rcx,%rcx
push   %rcx
popf
add    %ecx,%eax
pushf
pop    %rcx
popf
mov    %rcx,-0x10(%rbp)
mov    %eax,-0x14(%rbp)
mov    -0x4(%rbp),%esi
mov    -0x8(%rbp),%edx
mov    -0x14(%rbp),%ecx
mov    -0x10(%rbp),%rdi
and    $0x1,%rdi
xor    %r8d,%r8d
mov    $0x1,%eax
cmp    $0x0,%rdi
cmovne %eax,%r8d
mov    -0x10(%rbp),%rdi
and    $0x800,%rdi
xor    %r9d,%r9d
mov    $0x1,%eax
cmp    $0x0,%rdi
cmovne %eax,%r9d
lea    0xe87(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<test_add>:
mov    %esi,%edx
mov    %edi,%esi
mov    %edx,%ecx
pushf
xor    %r9,%r9
push   %r9
popf
add    %edi,%ecx
pushf
pop    %r9
popf
mov    %r9d,%r8d
and    $0x1,%r8d
shr    $0xb,%r9d
and    $0x1,%r9d
lea    0xec7(%rip),%rdi
xor    %eax,%eax
jmp    1030 <printf@plt>

LLVM IR (-O0):
@.str = [22 x i8] c"%08x:%08x:%08x:%x:%x\0A\00"
define void @test_add(i32 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i64
%6 = alloca i32
store i32 %0, i32* %3
store i32 %1, i32* %4
%7 = load i32, i32* %3
%8 = load i32, i32* %4
%9 = call { i64, i32 } asm sideeffect "pushf\0Axorq $0, $0\0Apush $0\0Apopf\0Aaddl $2, $1\0Apushf\0Apop $0\0Apopf\0A", "=r,=r,r,1,~{dirflag},~{fpsr},~{flags}"(i32 %7, i32 %8)
%10 = extractvalue { i64, i32 } %9, 0
%11 = extractvalue { i64, i32 } %9, 1
store i64 %10, i64* %5
store i32 %11, i32* %6
%12 = load i32, i32* %3
%13 = load i32, i32* %4
%14 = load i32, i32* %6
%15 = load i64, i64* %5
%16 = and i64 %15, 1
%17 = icmp ne i64 %16, 0
%18 = zext i1 %17 to i64
%19 = select i1 %17, i32 1, i32 0
%20 = load i64, i64* %5
%21 = and i64 %20, 2048
%22 = icmp ne i64 %21, 0
%23 = zext i1 %22 to i64
%24 = select i1 %22, i32 1, i32 0
%25 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str, i64 0, i64 0), i32 %12, i32 %13, i32 %14, i32 %19, i32 %24)
ret void
}

LLVM IR (-O2):
@.str = [22 x i8] c"%08x:%08x:%08x:%x:%x\0A\00"
define void @test_add(i32 %0, i32 %1) {
%3 = tail call { i64, i32 } asm sideeffect "pushf\0Axorq $0, $0\0Apush $0\0Apopf\0Aaddl $2, $1\0Apushf\0Apop $0\0Apopf\0A", "=r,=r,r,1,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %1)
%4 = extractvalue { i64, i32 } %3, 0
%5 = extractvalue { i64, i32 } %3, 1
%6 = trunc i64 %4 to i32
%7 = and i32 %6, 1
%8 = lshr i32 %6, 11
%9 = and i32 %8, 1
%10 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([22 x i8], [22 x i8]* @.str, i64 0, i64 0), i32 %0, i32 %1, i32 %5, i32 %7, i32 %9)
ret void
}