void printi_args2(char *sign, double x, double y, double prod) {
  char *v1 = fltstr(x), *v2 = fltstr(y), *v3 = fltstr(prod);
  printf("   |%s%s%s%s%s%s%s = %s%s%s\n", "\e[35m", v1, "\e[0m", sign, "\e[35m",
         v2, "\e[0m", "\e[35m", v3, "\e[0m");
  free(v1), free(v2), free(v3);
}


x86 assembly (clang, -O0):
<printi_args2>:
push   %rbp
mov    %rsp,%rbp
push   %rbx
sub    $0x68,%rsp
mov    %rdi,-0x10(%rbp)
movsd  %xmm0,-0x18(%rbp)
movsd  %xmm1,-0x20(%rbp)
movsd  %xmm2,-0x28(%rbp)
movsd  -0x18(%rbp),%xmm0
mov    $0x1,%al
call   1050 <fltstr@plt>
cltq
mov    %rax,-0x30(%rbp)
movsd  -0x20(%rbp),%xmm0
mov    $0x1,%al
call   1050 <fltstr@plt>
cltq
mov    %rax,-0x38(%rbp)
movsd  -0x28(%rbp),%xmm0
mov    $0x1,%al
call   1050 <fltstr@plt>
cltq
mov    %rax,-0x40(%rbp)
mov    -0x30(%rbp),%rdx
mov    -0x10(%rbp),%r8
mov    -0x38(%rbp),%rbx
mov    -0x40(%rbp),%r10
lea    0xe67(%rip),%rdi
lea    0xe7d(%rip),%r11
lea    0xe7c(%rip),%rax
mov    %r11,%rsi
mov    %rax,%rcx
mov    %r11,%r9
mov    %rbx,(%rsp)
mov    %rax,0x8(%rsp)
mov    %r11,0x10(%rsp)
mov    %r10,0x18(%rsp)
mov    %rax,0x20(%rsp)
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x30(%rbp),%rdi
call   1030 <free@plt>
mov    -0x38(%rbp),%rdi
call   1030 <free@plt>
mov    -0x40(%rbp),%rdi
call   1030 <free@plt>
add    $0x68,%rsp
pop    %rbx
pop    %rbp
ret

x86 assembly (clang, -O2):
<printi_args2>:
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x18,%rsp
movsd  %xmm2,0x10(%rsp)
movsd  %xmm1,0x8(%rsp)
mov    %rdi,%r12
mov    $0x1,%al
call   1050 <fltstr@plt>
movslq %eax,%r14
movsd  0x8(%rsp),%xmm0
mov    $0x1,%al
call   1050 <fltstr@plt>
movslq %eax,%r15
movsd  0x10(%rsp),%xmm0
mov    $0x1,%al
call   1050 <fltstr@plt>
movslq %eax,%rbx
sub    $0x8,%rsp
lea    0xea4(%rip),%rcx
lea    0xe97(%rip),%rsi
lea    0xe73(%rip),%rdi
mov    %r14,%rdx
mov    %r12,%r8
mov    %rsi,%r9
xor    %eax,%eax
push   %rcx
push   %rbx
push   %rsi
push   %rcx
push   %r15
call   1040 <printf@plt>
add    $0x30,%rsp
mov    %r14,%rdi
call   1030 <free@plt>
mov    %r15,%rdi
call   1030 <free@plt>
mov    %rbx,%rdi
add    $0x18,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
jmp    1030 <free@plt>

LLVM IR (-O0):
@.str = [29 x i8] c" |%s%s%s%s%s%s%s = %s%s%s\0A\00"
@.str.1 = [6 x i8] c"\1B[35m\00"
@.str.2 = [5 x i8] c"\1B[0m\00"
define void @printi_args2(i8* %0, double %1, double %2, double %3) {
%5 = alloca i8*
%6 = alloca double
%7 = alloca double
%8 = alloca double
%9 = alloca i8*
%10 = alloca i8*
%11 = alloca i8*
store i8* %0, i8** %5
store double %1, double* %6
store double %2, double* %7
store double %3, double* %8
%12 = load double, double* %6
%13 = call i32 (double, ...) bitcast (i32 (...)* @fltstr to i32 (double, ...)*)(double %12)
%14 = sext i32 %13 to i64
%15 = inttoptr i64 %14 to i8*
store i8* %15, i8** %9
%16 = load double, double* %7
%17 = call i32 (double, ...) bitcast (i32 (...)* @fltstr to i32 (double, ...)*)(double %16)
%18 = sext i32 %17 to i64
%19 = inttoptr i64 %18 to i8*
store i8* %19, i8** %10
%20 = load double, double* %8
%21 = call i32 (double, ...) bitcast (i32 (...)* @fltstr to i32 (double, ...)*)(double %20)
%22 = sext i32 %21 to i64
%23 = inttoptr i64 %22 to i8*
store i8* %23, i8** %11
%24 = load i8*, i8** %9
%25 = load i8*, i8** %5
%26 = load i8*, i8** %10
%27 = load i8*, i8** %11
%28 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i8* %24, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* %25, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i8* %26, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i8* %27, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0))
%29 = load i8*, i8** %9
%30 = load i8*, i8** %10
%31 = load i8*, i8** %11
ret void
}

LLVM IR (-O2):
@.str = [29 x i8] c" |%s%s%s%s%s%s%s = %s%s%s\0A\00"
@.str.1 = [6 x i8] c"\1B[35m\00"
@.str.2 = [5 x i8] c"\1B[0m\00"
define void @printi_args2(i8* %0, double %1, double %2, double %3) {
%5 = tail call i32 (double, ...) bitcast (i32 (...)* @fltstr to i32 (double, ...)*)(double %1)
%6 = sext i32 %5 to i64
%7 = inttoptr i64 %6 to i8*
%8 = tail call i32 (double, ...) bitcast (i32 (...)* @fltstr to i32 (double, ...)*)(double %2)
%9 = sext i32 %8 to i64
%10 = inttoptr i64 %9 to i8*
%11 = tail call i32 (double, ...) bitcast (i32 (...)* @fltstr to i32 (double, ...)*)(double %3)
%12 = sext i32 %11 to i64
%13 = inttoptr i64 %12 to i8*
%14 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([29 x i8], [29 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i8* %7, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* %0, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i8* %10, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i8* %13, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.2, i64 0, i64 0))
tail call void @free(i8* %7)
tail call void @free(i8* %10)
tail call void @free(i8* %13)
ret void
}