Today I came across weird problem with floating point cast in LLVM IR. I'm using Windows 10, and llvm-3.5.2. I wrote this code in C:
#include <stdio.h>
int main() {
  double b = 2.0;
  float c = b;
  printf("%d\n", c == 2.0); 
  return 0;
}
And I used clang -S -emit-llvm and obtained this LLVM IR:
@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
; Function Attrs: nounwind
define i32 @main() #0 {
entry:
  %retval = alloca i32, align 4
  %b = alloca double, align 8
  %c = alloca float, align 4
  store i32 0, i32* %retval
  store double 2.000000e+00, double* %b, align 8
  %0 = load double* %b, align 8
  %conv = fptrunc double %0 to float
  store float %conv, float* %c, align 4
  %1 = load float* %c, align 4
  %conv1 = fpext float %1 to double
  %cmp = fcmp oeq double %conv1, 2.000000e+00
  %conv2 = zext i1 %cmp to i32
  %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %conv2) #1
  ret i32 0
}
; Function Attrs: nounwind
declare i32 @printf(i8*, ...) #0
Which executed (after llvm-as and lli) gave an incorrect result of 0 !
The problem seems to be in fpext which isn't very intuitive, because it should be this 'safe' conversion (better direction than fptrunc which is from double to float).
I think so, because when I change this line:
%cmp = fcmp oeq double %conv1, 2.000000e+00
to this:
%cmp = fcmp oeq float %1, 2.000000e+00
then the result is as expected 1.
So my question is why is it like that, why this conversion fails? Is this some kind of a bug in LLVM? Or there exists some better way of this type of conversion? Or maybe I wrote an unsafe code in C? If so, then there is a huge problem in using floats. I don't have an influence on clang when performing this conversions. For example let's say that I want to output c above. Then I write printf("%f", c) and clang generates code that casts c to double before passing it to printf. And the result is incorrect again. So how to safely print a float? How to safely use floats at all?
I'm not sure whether this problem appears on Linux too.
 
    